Pourquoi l’astérisque avant le nom de la variable, plutôt qu’après le type?

Pourquoi la plupart des programmeurs C nomment-ils des variables comme ceci:

int *myVariable; 

plutôt que comme ça:

 int* myVariable; 

Les deux sont valables. Il me semble que l’astérisque est une partie du type, pas une partie du nom de la variable. Quelqu’un peut-il expliquer cette logique?

Ils sont exactement équivalents. Cependant, dans

 int *myVariable, myVariable2; 

Il semble évident que myVariable a le type int * , alors que myVariable2 a le type int . Dans

 int* myVariable, myVariable2; 

il peut sembler évident que les deux sont de type int * , mais ce n’est pas correct car myVariable2 a le type int .

Par conséquent, le premier style de programmation est plus intuitif.

Si vous le regardez d’une autre manière, *myVariable est de type int , ce qui a du sens.

Parce que le * se lie plus étroitement à la variable qu’au type:

 int* varA, varB; // This is misleading 

Cependant, même les meilleures déclarations d’une seule ligne me semblent contre-intuitives, car le * fait partie du type. J’aime faire ça à la place:

 int* varA; int varB; 

Comme d’habitude, moins le code est compact, plus il est lisible. 😉

Quelque chose que personne n’a mentionné jusqu’ici, c’est que cet astérisque est en réalité “l’ opérateur de déréférencement ” en C.

 *a = 10; 

La ligne ci-dessus ne signifie pas que je veux atsortingbuer 10 à a , cela signifie que je veux assigner 10 à n’importe quel emplacement de mémoire sur lequel pointe a point. Et je n’ai jamais vu quelqu’un écrire

 * a = 10; 

Avez-vous? Donc, l’ opérateur de déréférence est presque toujours écrit sans espace. C’est probablement pour le distinguer d’une multiplication fractionnée sur plusieurs lignes:

 x = a * b * c * d * e * f * g; 

Ici, il serait trompeur, n’est-ce pas?

Ok, maintenant, que signifie la ligne suivante:

 int *a; 

La plupart des gens diraient:

Cela signifie que a est un pointeur sur une valeur int .

Ceci est techniquement correct, la plupart des gens aiment le voir / lire de cette façon et c’est ainsi que les normes C modernes le définiraient (notez que le langage C lui-même est antérieur à toutes les normes ANSI et ISO). Mais ce n’est pas la seule façon de voir les choses. Vous pouvez également lire cette ligne comme suit:

La valeur déréférencée de a est de type int .

Ainsi, l’astérisque dans cette déclaration peut également être considéré comme un opérateur de déréférencement, ce qui explique également son positionnement. Et le fait qu’un pointeur ne soit pas vraiment déclaré, il est implicite par le fait que la seule chose que vous pouvez réellement déréférencer est un pointeur.

Le standard C ne définit que deux significations pour l’opérateur * :

  • opérateur d’indirection
  • opérateur de multiplication

Et l’indirection n’est qu’une simple signification, il n’y a pas de signification supplémentaire pour déclarer un pointeur, il y a juste une indirection, ce que fait l’opération de déréférencement, elle effectue un access indirect, aussi dans une instruction comme int *a; c’est un access indirect ( * signifie un access indirect) et donc la seconde déclaration ci-dessus est beaucoup plus proche de la norme que la première.

Je vais aller sur une twig et dire qu’il y a une réponse directe à cette question , à la fois pour les déclarations de variables et pour les types de parameters et de retours, à savoir que l’astérisque devrait aller à côté du nom: int *myVariable; . Pour comprendre pourquoi, regardez comment vous déclarez d’autres types de symboles dans C:

int my_function(int arg); pour une fonction;

float my_array[3] pour un tableau.

Le modèle général, appelé déclaration suit l’utilisation , est que le type d’un symbole est divisé en une partie avant le nom et les parties autour du nom, et ces parties autour du nom imitent la syntaxe que vous utiliseriez pour obtenir un nom. valeur du type à gauche:

int a_return_value = my_function(729);

float an_element = my_array[2];

et: int copy_of_value = *myVariable; .

C ++ jette une clé dans les travaux avec des références, car la syntaxe au point où vous utilisez des références est identique à celle des types de valeur, vous pouvez donc argumenter que C ++ adopte une approche différente de C Comportement de C dans le cas des pointeurs, les références sont donc tout à fait exceptionnelles à cet égard.

C’est juste une question de préférence.

Lorsque vous lisez le code, la distinction entre les variables et les pointeurs est plus facile dans le second cas, mais cela peut créer de la confusion lorsque vous placez des variables et des pointeurs de type commun sur une seule ligne (elle-même souvent déconseillée par les directives du projet). parce que diminue la lisibilité).

Je préfère déclarer les pointeurs avec leur signe correspondant à côté du nom du type, par exemple

 int* pMyPointer; 

Un grand gourou a dit un jour “Lisez-le comme le compilateur, vous devez le faire.”

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

Certes, cela concernait le placement en const, mais la même règle s’applique ici.

Le compilateur le lit comme suit:

 int (*a); 

pas aussi:

 (int*) a; 

Si vous prenez l’habitude de placer l’écanvas à côté de la variable, vos déclarations seront plus faciles à lire. Il évite également les yeux tels que:

 int* a[10]; 

Parce que cela a plus de sens quand vous avez des déclarations comme:

 int *a, *b; 

Pour déclarer plusieurs pointeurs sur une ligne, je préfère int* a, * b; qui déclare plus intuitivement “a” comme un pointeur sur un entier, et ne mélange pas les styles en déclarant également “b”. Comme quelqu’un l’a dit, je ne déclarerais pas deux types différents dans la même déclaration.

Dans K & R, ils placent l’opérateur de pointeur à côté du nom de la variable plutôt que du type. Personnellement, je considère ce livre comme l’autorité suprême / la bible. Toujours en arrière-plan Objective-C, je suis la convention de nom *.

J’ai déjà répondu à une question similaire dans CP, et comme personne ne l’a mentionné, je dois également souligner que C est un langage de format libre , quel que soit le style choisi, alors que l’parsingur peut distinguer chaque jeton. Cette particularité de C conduit à un type de concours très particulier appelé concours d’obfuscation .