Tive o prazer recente de explicar indicadores para um iniciante em programação C e me deparei com a seguinte dificuldade. Pode não parecer um problema, se você já sabe usar ponteiros, mas tente observar o exemplo a seguir com uma mente clara:
int foo = 1;
int *bar = &foo;
printf("%p\n", (void *)&foo);
printf("%i\n", *bar);
Para o iniciante absoluto, a saída pode ser surpreendente. Na linha 2, ele / ela havia acabado de declarar * bar como & foo, mas na linha 4 acontece * bar é realmente foo em vez de & foo!
A confusão, você pode dizer, deriva da ambiguidade do símbolo *: na linha 2, é usado para declarar um ponteiro. Na linha 4, é usado como um operador unário que busca o valor em que o ponteiro aponta. Duas coisas diferentes, certo?
No entanto, essa "explicação" não ajuda em nada um iniciante. Introduz um novo conceito, apontando uma discrepância sutil. Este não pode ser o caminho certo para ensiná-lo.
Então, como Kernighan e Ritchie explicaram isso?
O operador unário * é o operador de indireção ou desreferenciação; quando aplicado a um ponteiro, ele acessa o objeto apontado pelo ponteiro. [...]
A declaração do ponteiro ip,
int *ip
pretende ser um mnemônico; diz que a expressão*ip
é um int. A sintaxe da declaração para uma variável imita a sintaxe das expressões nas quais a variável pode aparecer .
int *ip
deve ser lido como " *ip
retornará um int
"? Mas por que então a tarefa após a declaração não segue esse padrão? E se um iniciante quiser inicializar a variável? int *ip = 1
(leia: *ip
retornará um int
e o int
é 1
) não funcionará conforme o esperado. O modelo conceitual simplesmente não parece coerente. Estou faltando alguma coisa aqui?
Edit: Tentou resumir as respostas aqui .
*
em uma declaração é um token que significa "declarar um ponteiro", nas expressões é o operador de desreferência e que esses dois representam coisas diferentes que têm o mesmo símbolo (igual ao operador de multiplicação - mesmo símbolo, significado diferente). É confuso, mas qualquer coisa diferente do estado real das coisas será ainda pior.
int* bar
tornar mais óbvio que a estrela é realmente parte do tipo, não parte do identificador. Claro que isso leva a problemas diferentes com coisas não intuitivas, como int* a, b
.
*
pode ter dois significados diferentes, dependendo do contexto. Assim como a mesma letra pode ser pronunciada de maneira diferente, dependendo da palavra em que ela fica difícil de aprender a falar muitas línguas. Se todo conceito / operação tivesse seu próprio símbolo, precisaríamos de teclados muito maiores, para que os símbolos sejam reciclados quando fizer sentido.
int* p
), enquanto avisa o aluno contra o uso de várias declarações na mesma linha quando houver ponteiros. Quando o aluno entender completamente o conceito de ponteiros, explique ao aluno que a int *p
sintaxe é equivalente e depois explique o problema com várias declarações.