J'ai récemment décidé que je devais enfin apprendre le C/C++, et il y a une chose que je ne comprends pas vraiment à propos des pointeurs ou plus précisément de leur définition.
Que diriez-vous de ces exemples:
int* test;
int *test;
int * test;
int* test,test2;
int *test,test2;
int * test,test2;
Si je comprends bien, les trois premiers cas font tous la même chose: Test n’est pas un int, mais un pointeur sur un.
La deuxième série d’exemples est un peu plus délicate. Dans le cas 4, test et test2 seront des pointeurs sur un int, alors que dans le cas 5, seul test est un pointeur, alors que test2 est un "réel" int. Qu'en est-il du cas 6? Identique au cas 5?
4, 5 et 6 sont la même chose, seulement test est un pointeur. Si vous voulez deux pointeurs, vous devriez utiliser:
int *test, *test2;
Ou encore mieux (pour que tout soit clair):
int* test;
int* test2;
Les espaces blancs autour des astérisques n'ont aucune signification. Les trois signifient la même chose:
int* test;
int *test;
int * test;
Le "int *var1, var2
" est une syntaxe perverse destinée uniquement à confondre les gens et qui devrait être évitée. Il s'étend à:
int *var1;
int var2;
Utilisez le "Clockwise Spiral Rule" pour aider à analyser les déclarations C/C++;
Il y a trois étapes simples à suivre:
En commençant par l'élément inconnu, déplacez-vous en spirale/dans le sens des aiguilles d'une montre direction; lorsque vous rencontrez les éléments suivants, remplacez-les par les déclarations en anglais correspondantes:
[X]
ou[]
: taille de tableau X de ... ou taille de tableau non définie de ...
(type1, type2)
: fonction passant les types1 et 2 retournant ...
*
: pointeur (s) sur ...- Continuez à faire cela dans une direction en spirale/dans le sens des aiguilles d'une montre jusqu'à ce que tous les jetons aient été recouverts.
- Toujours résoudre tout ce qui est entre parenthèses en premier!
En outre, les déclarations doivent être dans des déclarations séparées lorsque cela est possible (ce qui est vrai dans la grande majorité des cas).
De nombreuses directives de codage recommandent de déclarer uniquement une variable par ligne . Cela évite toute confusion de ce que vous aviez avant de poser cette question. La plupart des programmeurs C++ avec lesquels j'ai travaillé semblent s'en tenir à cela.
Je sais que je suis un peu à part, mais quelque chose que j’ai trouvé utile est de lire les déclarations à l’arrière.
int* test; // test is a pointer to an int
Cela commence à très bien fonctionner, en particulier lorsque vous commencez à déclarer des pointeurs const et qu'il devient difficile de savoir si c'est le pointeur qui est const ou si c'est le paramètre pointé par le pointeur.
int* const test; // test is a const pointer to an int
int const * test; // test is a pointer to a const int ... but many people write this as
const int * test; // test is a pointer to an int that's const
#include <type_traits>
std::add_pointer<int>::type test, test2;
Comme d'autres l'ont mentionné, 4, 5 et 6 sont identiques. Souvent, les gens utilisent ces exemples pour argumenter que le *
appartient à la variable plutôt qu'au type. Bien que ce soit une question de style, il y a un débat quant à savoir si vous devriez penser et l'écrire de cette façon:
int* x; // "x is a pointer to int"
ou de cette façon:
int *x; // "*x is an int"
FWIW, je suis dans le premier camp, mais la raison pour laquelle les deux autres argumentent en faveur de la seconde forme est qu’elle résout (principalement) ce problème particulier:
int* x,y; // "x is a pointer to int, y is an int"
ce qui est potentiellement trompeur; à la place, vous écririez soit
int *x,y; // it's a little clearer what is going on here
ou si vous voulez vraiment deux pointeurs,
int *x, *y; // two pointers
Personnellement, je dis qu'il faut garder une variable par ligne, peu importe le style que vous préférez.
Dans 4, 5 et 6, test
est toujours un pointeur et test2
n'est pas un pointeur. L'espace blanc n'est (presque) jamais significatif en C++.
Vous pouvez penser aux points 4, 5 et 6 comme suit: variable.
Lors de la déclaration d'une variable de pointeur, j'ajoute toujours des espaces entre la variable et l'astérisque, même si j'en déclare plusieurs dans une ligne. Ne pas le faire me rend confus pour une expression de déréférencement presque à chaque fois.
Le pointeur est un modificateur du type. Il est préférable de les lire de droite à gauche afin de mieux comprendre comment l'astérisque modifie le type. 'int *' peut être lu comme "pointeur sur int". Dans plusieurs déclarations, vous devez spécifier que chaque variable est un pointeur ou elle sera créée en tant que variable standard.
1,2 et 3) Le test est de type (int *). Les espaces blancs ne comptent pas.
4,5 et 6) Le test est de type (int *). Test2 est de type int. Encore une fois, les espaces sont sans importance.
La logique en C est que vous déclarez les variables de la façon dont vous les utilisez. Par exemple
char *a[100];
dit que *a[42]
sera une char
. Et a[42]
un pointeur de caractère. Et donc a
est un tableau de pointeurs de caractères.
En effet, les auteurs du compilateur d'origine souhaitaient utiliser le même analyseur pour les expressions et les déclarations. (Ce n'est pas une raison très sensible pour un choix de conception de langage)
À mon avis, il est préférable de placer l'astérisque à côté du nom du pointeur, plutôt que du type. Comparez par exemple:
int *pointer1, *pointer2; // Fully consistent, two pointers
int* pointer1, pointer2; // Inconsistent, unexpected, and thus prone to errors
Pourquoi le second cas est-il incohérent? Parce que par exemple int x,y;
déclare deux variables du même type mais le type n'est mentionné qu'une seule fois dans la déclaration. Cela crée un précédent et un comportement attendu. Et int* pointer1, pointer2;
est incompatible avec cela.
Je dirais que la convention initiale consistait à placer l’étoile du côté du nom du pointeur (à droite de la déclaration).
dans le langage de programmation c} de Dennis M. Ritchie, les étoiles sont à droite de la déclaration.
en regardant le code source de Linux sous https://github.com/torvalds/linux/blob/master/init/main.c .__, nous pouvons voir que l'étoile est également du côté droit.
Vous pouvez suivre les mêmes règles, mais ce n'est pas grave si vous placez les étoiles du côté des caractères . Rappelez-vous que l'uniformité est importante; choisir.