Maneira correta de declarar variáveis ​​de ponteiro em C / C ++ [fechado]

90

Observei que algumas pessoas usam a seguinte notação para declarar variáveis ​​de ponteiro.

(a) char* p;

ao invés de

(b) char *p;

Eu uso (b). Qual é o racional por trás da notação (a)? A notação (b) faz mais sentido para mim porque o ponteiro de caractere não é um tipo em si. Em vez disso, o tipo é o caractere e a variável pode ser um ponteiro para o caractere.

char* c;

Parece que existe um tipo char * e a variável c é desse tipo. Mas, na verdade, o tipo é char e * c (a localização da memória apontada por c) é desse tipo (char). Se você declarar várias variáveis ​​ao mesmo tempo, essa distinção se torna óbvia.

char* c, *d;

Isso parece estranho. C e d são o mesmo tipo de ponteiros que apontam para um caractere. Neste desde o próximo parece mais natural.

char *c, *d;

Obrigado.

Keeda
fonte
7
O que você quer dizer com ponteiro char não é um tipo? Você está dizendo que um ponteiro não é um tipo?
Benjamin Lindley
1
Acredito que seja uma questão de preferência, a menos que você esteja olhando um guia de estilo específico (ou seja, sua empresa pode ter um determinado padrão de codificação que você deve seguir). Eu tendo a misturar entre a escolha be algum lugar no meio. Às vezes não acho que char *tpareça adequado, então posso char * t;sim. No entanto, tenho visto char* t;também com frequência .
RageD em
1
Além disso, seu raciocínio "o tipo é char e * c (a localização da memória apontada por c) é desse tipo (char)" parece indicar que há um char sendo declarado, quando na verdade não há. Se for tratada como tal, como às vezes é por iniciantes, certamente levará a violações de acesso à memória.
Benjamin Lindley
1
Ambos ainda são suficientemente descritivos, (b) mostra * p é do tipo chare (a) mostra p é umpointer to a char
Uma Pessoa
1
Com mais de uma década de experiência no setor, hoje foi a primeira vez que isso surgiu, e apenas na leitura de artigos de outros profissionais do setor. Obviamente, então, eu nunca tive nenhuma conversa tão religiosa sobre isso como tive com tabs x espaços, comentários por def ou dez, ou qualquer um dos outros tópicos do tipo "é bom não ter nada mais importante para discutir" . Sendo essa a minha perspectiva, eu preferi, tão tarde no jogo da minha carreira, ir com "char * p" na maioria das vezes. Sim, espaço antes, espaço depois. Principalmente porque eu acho que ele reduz os bugs, pois torna o ponteiro-ness mais óbvio.
Kit10 de

Respostas:

102

Bjarne Stroustrup disse:

A escolha entre "int * p;" e "int * p;" não é sobre certo e errado, mas sobre estilo e ênfase. C enfatizou expressões; as declarações eram freqüentemente consideradas pouco mais do que um mal necessário. C ++, por outro lado, dá grande ênfase aos tipos.

Um "programador C típico" escreve "int * p;" e explica "* p é o que é o int" enfatizando a sintaxe, e pode apontar para a gramática de declaração C (e C ++) para argumentar pela correção do estilo. Na verdade, o * liga-se ao nome p na gramática.

Um "programador C ++ típico" escreve "int * p;" e explica "p é um ponteiro para um tipo int" enfatizando. Na verdade, o tipo de p é int *. Eu claramente prefiro essa ênfase e a vejo como importante para usar bem as partes mais avançadas do C ++.

Fonte: http://www.stroustrup.com/bs_faq2.html#whitespace

Eu recomendaria o último estilo porque na situação em que você está declarando vários ponteiros em uma única linha (seu 4º exemplo), ter o asterisco com a variável será o que você está acostumado.

BlackJack
fonte
34
Outros recomendam nunca declarar vários objetos na mesma declaração. :-)
Bo Persson
5
Enfatizo a lógica por trás da sintaxe, portanto, prefiro :, int *psignificando: quando pé desreferenciado, recebo um int. Então, várias declarações separadas por ,faz sentido: int *p, *q, r(quando pou qé desreferenciado recebo um int, quando ré referenciado recebo um int). Além disso, a sintaxe do ponteiro de função faz sentido: int (*f)()(quando fé desreferenciado e chamado recebo um int). E isso faz sentido: int *p, (*f)().
Druesukker de
2
Isso me ajudou a perceber que há validade para o outro lado do argumento. Sendo, principalmente, um programador de alto nível, enfatizo o tipo; e preferir int*. Para mim, int *p, (*f)()não faz muito sentido, mas posso ver como seria para algumas pessoas em algumas situações.
Assimilater
1
@Druesukker, sua declaração faz mais sentido do que qualquer uma das anteriores, eu acho.
Muntashir Akon
1
@Druesukker Mas a lógica não funciona exatamente para void*(e não funciona para referências C ++).
Jamesdlin
57

Eu pessoalmente prefiro colocar o *com o resto do tipo

char* p;  // p is a pointer to a char.

As pessoas vão argumentar "mas então char* p, q;se torna enganoso", ao que eu digo, "então não faça isso".

ikegami
fonte
Muito bom argumento para o char * p; escolha :) Não me importo com nenhum deles, desde que não fique difícil de ler como o exemplo que você mostrou, caso em que eles não deveriam estar fazendo isso.
Jesus Ramos
1
E quando você deseja enviar o valor? Você faz cout << *p;. Então, por que não colocar a estrela antes da p declaração *p:? Na minha opinião, seria menos confuso.
user1170330
13
@ user1170330, porque em um lugar faz parte da definição de tipo e é um operador de desreferência no outro. Nenhuma relação. Na verdade, é bom que eles tenham uma aparência diferente, já que coisas diferentes devem ser diferentes.
ikegami
32

Não há diferença em como escrever. Mas se você quiser declarar dois ou mais ponteiros em uma linha, é melhor usar a variante (b), porque é claro o que você deseja. Olhe abaixo:

int *a;
int* b;      // All is OK. `a` is pointer to int ant `b` is pointer to int
char *c, *d; // We declare two pointers to char. And we clearly see it.
char* e, f;  // We declare pointer `e` and variable `f` of char type.
             // Maybe here it is mistake, maybe not. 
// Better way of course is use typedef:
typedef char* PCHAR;
PCHAR g, h;  // Now `g` and `h` both are pointers.
// If we used define construction for PCHAR we'd get into problem too.
George Gaál
fonte
5
typedefnão é a melhor maneira "claro". Algumas pessoas podem preferir isso, mas é problemático se houver várias pessoas trabalhando com seu código. Se não estiver acostumado PCHAR, posso escrever algo como PCHAR *p;, que seria um char**e não o que pretendo. Em geral, se você quiser um char**, terá que escrever PCHAR*ou definir um novo tipo, e então ele simplesmente começará a se tornar estúpido.
BlackJack
3
Se for necessário algum tipo de ponteiro complexo, como ponteiro para função, é uma boa idéia criar typedefs. Eles tornam o código muito mais simples neste caso. Por outro lado, usar o PCHAR é um exemplo mais sintético do que a prática diária. Mas claramente faz o que você deseja. e então começa a ficar estúpido Por favor, encaminhe todas as reclamações para Stroustrup :-)
George Gaál
Se você escreveu PCHAR * p para definir um ponteiro para char, seria óbvio que você não sabe o que está fazendo e não leu o tipo def. A resposta está na opinião dele. Há outro benefício para o typedef; em C, está nas maneiras fáceis de tornar as coisas opacas. publicamente ter o símbolo definido como VOID ptr, privativamente o tipo def é outra coisa ... Prefiro ajustar um typedef de vez em quando, em seguida, ajustar tudo em todo o código quando mudamos algo sobre um dos tipos ... mas C ++ 11 aborda muito disso com auto
UpAndAdam
Para alguém que está tentando voltar a brincar com C ++ cinco anos depois da faculdade, esta é uma das melhores respostas.
Panzercrisis
10

O compromisso é

char * p;

K&R usa

char *p;

Depende de você, a menos que esteja seguindo um padrão de codificação - nesse caso, você deve seguir o que todo mundo faz.

jnnnnn
fonte
4
Eu aprendi da maneira mais difícil que char * x, y não significa que y é um char *. Agora posso ver porque K&R segue esse estilo.
Rahul Kadukar,
o que é K&R e por que importa o que uma única fonte de código usa? Eu uso char* p;. é uma questão de estilo, não de convenção ou regras. para mim, faz mais sentido que p seja do tipo char*, então, obviamente, o * deveria estar com o tipo.
FalcoGer 01 de
@FalcoGer Eu adicionei um link para K&R. Não importa o que uma única fonte de código usa. Sua equipe pode ficar irritada com você se você não seguir o padrão deles, porque você os está fazendo trabalhar mais para entender seu código. Hoje em dia, espero que as equipes estejam usando de clang-formatqualquer maneira.
jnnnnn
2

É tudo uma questão de preferência, pessoalmente em projetos que vejo o char *, tendo a declarar vários ponteiros em linhas separadas. Não existe uma maneira "correta" real de fazer isso e tudo se resume à preferência. Alguns dizem que é mais fácil ler (a) enquanto outros dizem que (b) é mais fácil declarar mais variáveis ​​do mesmo tipo na mesma linha.

Acho que (b) é mais comum e, em alguns casos, tenho visto

char * a;

ou algo parecido com isto. De novo preferência. O que quer que você se sinta confortável ou qualquer projeto em que estou trabalhando, usarei (a menos que eu mesmo escreva, caso em que uso (a))

Jesus Ramos
fonte