por RobL » 07 Abr 2010 11:11
Primeiro, nunca perca de vista que só existe bits, byte, words, etc.
Se você já trabalhou com assembly, você sempre trabalhou com "ponteiros"!!!.
Sempre que escreveu na memo foi através da idéia de ponteiro, similar a usar endereçamento indireto, no PIC o registro INDF tem exatamente a idéia de um ponteiro.
A seguir, não vem normalmente nos textos sobre ponteiros.
Em C, ponteiro passa a ser uma abstração. Um programador em C aprende ponteiro sem necessitar saber que vai setar circuitos eletrônicos chamados flip flops (8 deles) formando um byte.
Abaixo vamos concretizar a idéia de ponteiros, o que não é relevante para um programador em C, mas sim para quem não consegue abstrair e quer "ver" o ponteiro em ação:
Em C, quando você declara uma variável, você reserva um espaço na memo (algo real, concreto). Quando você declara um ponteiro, para inteiro, você reservou dois bytes para essa variável (nos microcontroladores de 8 bits)
int *ponteiro ;// reservou dois bytes para o nome ponteiro. O compilador vai reservar automaticamente, mas há como você dizer também onde quer este ponteiro (endereço), mas normalmente isto não tem interesse.
Suponha que o endereço de seu ponteiro, os bytes reservados sejam 0x00 e 0x01 (aqui está os bytes do ponteiro, sem nada dentro) apenas o endereço reservado para ele. Esses bytes é o ponteiro de nome ponteiro.
Agora você precisa colocar nesses dois bytes um endereço de memória ram.
Vamos fazer apontar para o endereço 0x20.
ponteiro = (int *) (0x20) ;// agora o ponteiro aponta para 0x20.
Dentro dos bytes 0x00 e 0x01 está o endereço de 0x20 (0x0020).
Agora vem uma outra abstração (mágica) que é devido a uma rotina nativa do C.
Esta é a mágica, há um "programa" dentro do C que lida com o ponteiro!!!
Quando você fizer:
*ponteiro = 5 ; Um programa nativo do C colocará na memo de endereço 0X20 o valor 0x5 (5d). Agora sim, nada de mágica, é um programa interno do C.
se criar um int:
int val ;
e fizer
val = *ponteiro;
Uma rotina nativa de C, olhará para o endereço 0x00 0x01 pegará o valor que está dentro dele, o byte 0x20, e vai lá na memo 0x20 e pega o valor que está nela, o número 5 e vai associar a val.
Cabe notar que val é outra memo que está em algum endereço. Suponha que val esteja em 0x45.
Olha isso agora:
ponteiro = &val ; // uma rotina nativa dentro do C pegou o valor 0x45 e botou dentro da variável ponteiro, ou seja, o endereço 0x00 0x01 tem o valor 0x0045.
Agora o ponteiro de nome ponteiro está apontando para val na memo 0x45. Dentro da memo 0x45 tem o valor 0x5.
Os bytes 0x00 e0x01 agora tem o valor 0x0045, ou seja ele aponta para 0x45 devido à rotina interna do C. Sempre que mexer com o nome ponteiro a rotina entra em ação se dirigindo para a memo 0x45.
Se fizermos:
printf ("valor do ponteiro %d \n", *ponteiro);
novamente a rotina interna do C para ponteiros vai olhar para o endereço do nome "ponteiro" 0x00 0x01 que está apontando para o endereço 0x45 e pega o valor dentro de 0x45 o número 0x5. Portanto printf vai dar saída o valor 5 decimal.
Se fizermos :
ponteiro++, dentro do endereço 0x00 0x01 estará agora o endereço 0x47, pois um inteiro ocupa 0x45 e 0x46(dois bytes). Se o ponteiro fosse definido como byte (unsigned char), após ponteiro++, apontaria para 0x46 e não para 0x47. Como inteiro o ponteiro vai de 2 em 2 bytes.
Se você definir um ponteiro para byte (unsigned char), você pode percorrer a memo byte por byte. Para que?
Suponha que você queira em um inteiro que tem 2 bytes, pegar um deles, operação essa muito comum.
Define-se um outro ponteiro para byte:
unsigned char *ptr ;
aponto ptr para o endereço da variável val acima :
ptr = &val; // ptr passa a ter o endereço 0x45 (val).
Note prt é um ponteiro para byte. Val é um inteiro com 2 bytes.
ptr está apontando para o endereço 0x45. Exatamente o byte low de val.
Vamos definir:
unsigned char blow, bhi;
blow = *ptr; // pegamos o byte low do inteiro val.
ptr++; // apontou para 0x46 byte hi de val.
bhi = *ptr ; // pegamos o byte alto do inteiro val.
Faça o que quizer com eles agora inclusive um swap.
Sacou???? Com ponteiros você acessa qualquer coisa (objeto). Sem eles
não acessa coisa alguma.
Em funções, passagem por referência, para alterar o valor da variável, em C só com ponteiros.
Pode parecer que ponteiro é só uma questão de comodidade, mas não é. Em C ele é peça fundamental, especialmente em funções. Visto que C é uma função (main) que contém todas as demais, já viu né.
Portanto C sem ponteiros, não é possível!!!
Se deu para entender, lendo os links acima deve ficar mais claro.
Deve ter alguns erros ai em cima, mas aí o pessoal corrige.
Editado pela última vez por
RobL em 07 Abr 2010 13:01, em um total de 1 vez.