web-dev-qa-db-fra.com

Emplacement de l'astérisque dans les déclarations de pointeur

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:

  1. int* test;
  2. int *test;
  3. int * test;
  4. int* test,test2;
  5. int *test,test2;
  6. 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?

71
Michael Stum

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;
116
Milan Babuškov

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;
41
Ates Goral

Utilisez le "Clockwise Spiral Rule" pour aider à analyser les déclarations C/C++; 

Il y a trois étapes simples à suivre:

  1. 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 ...

  2. 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. 
  3. 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).

32
Michael Burr

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
29
Scott Langham
#include <type_traits>

std::add_pointer<int>::type test, test2;
11
fredoverflow

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.

11
huskerchad

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++.

5
1800 INFORMATION

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.

1
dxh

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.

1
Ron Warholic

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)

0
Michel Billaud

À 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.

0
deLock

Je dirais que la convention initiale consistait à placer l’étoile du côté du nom du pointeur (à droite de la déclaration).

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. 

0
TheDrev