Muita confusão sobre os ponteiros C vem de uma escolha muito ruim que foi feita originalmente em relação ao estilo de codificação, corroborada por uma pequena escolha muito ruim na sintaxe da linguagem.
int *x = NULL;
está correto C, mas é muito enganoso, eu diria até sem sentido, e tem dificultado o entendimento da língua para muitos novatos. Isso nos faz pensar que mais tarde poderíamos fazer o *x = NULL;
que é obviamente impossível. Veja, o tipo da variável não é int
, e o nome da variável não *x
, nem o *
na declaração desempenha qualquer papel funcional em colaboração com o =
. É puramente declarativo. Então, o que faz muito mais sentido é o seguinte:
int* x = NULL;
que também é C correto, embora não adira ao estilo de codificação original K&R. Isso torna perfeitamente claro que o tipo é int*
, e a variável de ponteiro é x
, portanto, torna-se evidente até mesmo para os não iniciados que o valor NULL
está sendo armazenado em x
, que é um ponteiro para int
.
Além disso, torna mais fácil derivar uma regra: quando a estrela está fora do nome da variável, então é uma declaração, enquanto a estrela sendo anexada ao nome é a desreferenciação do ponteiro.
Então, agora fica muito mais compreensível que mais adiante podemos fazer x = NULL;
ou, *x = 2;
em outras palavras, torna mais fácil para um novato ver como variable = expression
leva a pointer-type variable = pointer-expression
e dereferenced-pointer-variable = expression
. (Para os iniciados, por 'expressão' quero dizer 'rvalue'.)
A escolha infeliz na sintaxe da linguagem é que, ao declarar variáveis locais, você pode dizer o int i, *p;
que declara um inteiro e um ponteiro para um inteiro, o que leva a crer que o *
é uma parte útil do nome. Mas não é, e essa sintaxe é apenas um caso especial peculiar, adicionado por conveniência e, em minha opinião, nunca deveria ter existido, porque invalida a regra que propus acima. Pelo que eu sei, em nenhum outro lugar da linguagem esta sintaxe é significativa, mas mesmo se for, ela aponta para uma discrepância na maneira como os tipos de ponteiro são definidos em C. Em todos os outros lugares, em declarações de variável única, em listas de parâmetros, em membros de estrutura, etc., você pode declarar seus ponteiros como em type* pointer-variable
vez de type *pointer-variable
; é perfeitamente legal e faz mais sentido.
int *x = whatever;
faz e o queint *x; *x = whatever;
faz.int *x = whatever;
realmente se comporta comoint *x; x = whatever;
, não*x = whatever;
.