Un grand nombre des arguments de cette rubrique sont simplement subjectifs et l'argument concernant «l'étoile se lie au nom de la variable» est naïf. Voici quelques arguments qui ne sont pas que des opinions:
Les qualificatifs de type de pointeur oublié
Formellement, l'étoile n'appartient ni au type ni au nom de la variable, elle fait partie de son propre élément grammatical nommé pointer . La syntaxe formelle C (ISO 9899: 2018) est:
(6.7) déclaration:
spécificateurs de déclaration init-declarator-list opt ;
Où les spécificateurs de déclaration contiennent le type (et le stockage) et la liste init-declarator-list contient le pointeur et le nom de la variable. Ce que nous voyons si nous disséquons davantage la syntaxe de cette liste de déclarateurs:
(6.7.6) déclarateur:
pointeur opt déclarateur direct
...
(6.7.6) pointeur:
*
type-qualifier-list opt
*
type-qualifier-list opt pointeur
Lorsqu'un déclarateur est la déclaration complète, un déclarateur direct est l'identificateur (nom de la variable) et un pointeur est l'étoile suivie d'une liste de qualificatifs de type facultatifs appartenant au pointeur lui-même.
Ce qui rend incohérents les différents arguments de style concernant "l'étoile appartient à la variable", c'est qu'ils ont oublié ces qualificatifs de type pointeur. int* const x
, int *const x
ou int*const x
?
Considérez int *const a, b;
, quels sont les types de a
et b
? Pas si évident que "l'étoile appartient à la variable" plus longtemps. Au contraire, on commencerait à se demander où const
appartient le.
Vous pouvez certainement faire un argument valable selon lequel l'étoile appartient au qualificatif de type pointeur, mais pas beaucoup au-delà.
La liste des qualificatifs de type pour le pointeur peut poser des problèmes à ceux qui utilisent le int *a
style. Ceux qui utilisent des pointeurs à l'intérieur d'un typedef
(ce que nous ne devrions pas, très mauvaise pratique!) Et pensent que "l'étoile appartient au nom de la variable" ont tendance à écrire ce bogue très subtil:
typedef int *bad_idea_t;
...
void func (const bad_idea_t *foo);
Cela compile proprement. Maintenant, vous pourriez penser que le code est rendu correct. Pas si! Ce code est accidentellement une fausse exactitude de const.
Le type de foo
est en fait int*const*
- le pointeur le plus extérieur a été rendu en lecture seule, pas les données pointées. Donc, à l'intérieur de cette fonction, nous pouvons le faire **foo = n;
et cela changera la valeur de la variable dans l'appelant.
En effet, dans l'expression const bad_idea_t *foo
, le *
n'appartient pas au nom de la variable ici! En pseudo-code, cette déclaration de paramètre doit être lue comme const (bad_idea_t *) foo
et non comme (const bad_idea_t) *foo
. L'étoile appartient au type pointeur masqué dans ce cas - le type est un pointeur et un pointeur qualifié const est écrit comme *const
.
Mais alors la racine du problème dans l'exemple ci-dessus est la pratique de cacher des pointeurs derrière un typedef
et non le *
style.
Concernant la déclaration de plusieurs variables sur une seule ligne
La déclaration de plusieurs variables sur une seule ligne est largement reconnue comme une mauvaise pratique 1) . CERT-C résume bien cela comme:
DCL04-C. Ne déclarez pas plus d'une variable par déclaration
Il suffit de lire l'anglais, accepte alors de bon sens que la déclaration devrait être une déclaration.
Et peu importe si les variables sont des pointeurs ou non. Déclarer chaque variable sur une seule ligne rend le code plus clair dans presque tous les cas.
Donc, l'argument selon lequel le programmeur est confus int* a, b
est mauvais. La racine du problème est l'utilisation de plusieurs déclarateurs, et non le placement du fichier *
. Quel que soit le style, vous devriez plutôt écrire ceci:
int* a;
int b;
Un autre argument sain mais subjectif serait que, étant donné que int* a
le type de a
est indiscutable int*
, l'étoile appartient donc au qualificatif de type.
Mais au fond, ma conclusion est que bon nombre des arguments présentés ici sont simplement subjectifs et naïfs. Vous ne pouvez pas vraiment faire un argument valable pour l'un ou l'autre style - c'est vraiment une question de préférence personnelle subjective.
1) CERT-C DCL04-C .
typedefs
, mais cela ajoutera une complexité inutile, à mon humble avis.