Méthode correcte de déclaration des variables de pointeur en C / C ++ [fermé]

91

J'ai remarqué que certaines personnes utilisent la notation suivante pour déclarer des variables de pointeur.

(a) char* p;

au lieu de

(b) char *p;

J'utilise (b). Quel est le rationnel derrière la notation (a)? La notation (b) a plus de sens pour moi car le pointeur de caractère n'est pas un type lui-même. Au lieu de cela, le type est un caractère et la variable peut être un pointeur vers le caractère.

char* c;

Cela ressemble à un type char * et la variable c est de ce type. Mais en fait, le type est char et * c (l'emplacement mémoire pointé par c) est de ce type (char). Si vous déclarez plusieurs variables à la fois, cette distinction devient évidente.

char* c, *d;

Cela a l'air bizarre. Les deux c et d sont les mêmes types de pointeurs qui pointent vers un caractère. En cela puisque le suivant semble plus naturel.

char *c, *d;

Merci.

keeda
la source
7
Que voulez-vous dire que le pointeur de caractères n'est pas un type? Êtes-vous en train de dire qu'un pointeur n'est pas un type?
Benjamin Lindley
1
Je pense que c'est une question de préférence, sauf si vous regardez un guide de style particulier (c'est-à-dire que votre entreprise peut avoir une certaine norme de codage que vous devez suivre). J'ai tendance à mélanger le choix entre le choix b et certains endroits au milieu. Parfois, je ne me sens pas char *tbien, alors je peux le faire à la char * t;place. Cependant, je l'ai souvent vu char* t;aussi.
RageD
1
De plus, votre raisonnement «le type est char et * c (l'emplacement mémoire pointé par c) est de ce type (char)» semble indiquer qu'il y a un caractère déclaré, alors qu'en fait, il n'y en a pas. S'il est traité comme tel, comme c'est parfois le cas par les débutants, cela conduira très certainement à des violations d'accès mémoire.
Benjamin Lindley
1
Les deux sont encore suffisamment descriptifs, (b) montre que * p est de type charet (a) montre que p est unpointer to a char
Une personne
1
Avec plus d'une décennie d'expérience dans l'industrie, c'était la première fois aujourd'hui que cela se présentait, et seulement en lisant des articles d'autres professionnels de l'industrie. Évidemment, alors, je n'ai jamais eu de conversation religieuse à ce sujet comme j'ai eu avec les onglets v espaces, les commentaires par def ou dec, ou tout autre sujet "c'est bien de n'avoir rien de plus important à discuter" . Cela étant mon point de vue, j'ai préféré, si tard dans le jeu de ma carrière, aller avec "char * p" le plus souvent. Oui, espace avant, espace après. Surtout que je trouve que cela réduit les bogues, car cela rend le pointeur plus évident.
Kit 10

Réponses:

102

Bjarne Stroustrup a déclaré:

Le choix entre "int * p;" et "int * p;" ne concerne pas le bien et le mal, mais le style et l’accent. C a mis l'accent sur les expressions; les déclarations n'étaient souvent considérées que comme un mal nécessaire. C ++, d'autre part, met fortement l'accent sur les types.

Un "programmeur C typique" écrit "int * p;" et l'explique "* p est ce qu'est la syntaxe int" accentuant, et peut pointer vers la grammaire de déclaration C (et C ++) pour argumenter en faveur de l'exactitude du style. En effet, le * se lie au nom p dans la grammaire.

Un "programmeur C ++ typique" écrit "int * p;" et l'explique "p est un pointeur vers un type de mise en valeur int". En effet, le type de p est int *. Je préfère clairement cet accent et le considère comme important pour bien utiliser les parties les plus avancées de C ++.

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

Je recommanderais ce dernier style car dans la situation où vous déclarez plusieurs pointeurs sur une seule ligne (votre 4ème exemple), avoir l'astérisque avec la variable sera ce à quoi vous êtes habitué.

BlackJack
la source
34
D'autres recommandent de ne jamais déclarer plusieurs objets dans la même déclaration. :-)
Bo Persson
5
J'insiste sur la logique derrière la syntaxe, donc je préfère:, int *pce qui signifie: quand pest déréférencé j'obtiens un int. Ensuite, plusieurs déclarations séparées par ont du ,sens: int *p, *q, r(quand pou qest déréférencé j'obtiens un int, quand rest référencé j'obtiens un int). En outre, la syntaxe du pointeur de fonction a du sens: int (*f)()(quand fest déréférencé et appelé, j'obtiens un int). Et cela est logique: int *p, (*f)().
Druesukker
2
Cela m'a aidé à réaliser qu'il y a de la validité de l'autre côté de l'argument. Étant principalement un programmeur de haut niveau, j'insiste sur le type; et préférez int*. Pour moi, cela int *p, (*f)()n'a pas beaucoup de sens, mais je peux en quelque sorte voir ce que cela ferait à certaines personnes dans certaines situations.
Assimilateur
1
@Druesukker, votre déclaration a plus de sens que tout ce qui précède, je pense.
Muntashir Akon
1
@Druesukker Mais la logique ne fonctionne pas exactement pour void*(et ne fonctionne pas du tout pour les références C ++).
jamesdlin
57

Personnellement je préfère placer le *avec le reste du type

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

Les gens argumenteront "mais char* p, q;deviendront alors trompeurs", ce à quoi je dis "alors ne faites pas cela".

ikegami
la source
Très bon argument pour le char * p; choix :) Cela ne me dérange aucun d'entre eux tant que cela ne devient pas difficile à lire comme l'exemple que vous avez montré, auquel cas ils ne devraient pas faire cela.
Jesus Ramos
1
Et quand vous voulez sortir la valeur? Vous faites cout << *p;. Alors pourquoi ne pas mettre l'étoile avant p lors de la déclaration *p:? À mon avis, ce serait moins déroutant.
user1170330
13
@ user1170330, Parce qu'à un endroit, il fait partie de la définition de type, et c'est un opérateur de déréférence dans l'autre. Pas de relation. Si quoi que ce soit, c'est une bonne chose qu'ils aient l'air différents, car différentes choses devraient être différentes.
ikegami
32

Il n'y a aucune différence comment écrire. Mais si vous voulez déclarer deux ou plusieurs pointeurs sur une ligne, mieux vaut utiliser la variante (b), car ce que vous voulez est clair. Regardez ci-dessous:

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
la source
5
typedefn'est pas une meilleure façon "bien sûr". Certaines personnes pourraient le préférer, mais c'est problématique si plusieurs personnes travaillent avec votre code. Si je ne suis pas habitué PCHAR, je pourrais écrire quelque chose comme PCHAR *p;, qui serait un char**et pas ce que je veux. En général, si vous voulez un char**, vous devez écrire PCHAR*ou définir un nouveau type, puis cela commence à devenir stupide.
BlackJack
3
Si vous avez besoin d'un type de pointeur complexe tel qu'un pointeur vers une fonction, il est très judicieux de créer des typedefs. Ils rendent le code beaucoup plus simple dans ce cas. En revanche, l'utilisation de PCHAR est un exemple plus synthétique que la pratique quotidienne. Mais cela fait clairement ce que vous voulez. et puis ça commence juste à devenir stupide Veuillez adresser toutes vos plaintes à Stroustrup :-)
George Gaál
Si vous avez écrit PCHAR * p pour définir un pointeur vers char, il serait évident que vous ne savez pas ce que vous faites et que vous n'avez pas lu le type def. La réponse est à son avis. Il y a un autre avantage au typedef; en C, il s'agit des moyens faciles de rendre les choses opaques. avoir publiquement le symbole défini comme VOID ptr, en privé le type def est autre chose ... Je préfère ajuster un typedef de temps en temps puis tout ajuster dans le code lorsque nous changeons quelque chose à propos de l'un des types ... mais C ++ 11 résout une grande partie de cela avec l'auto
UpAndAdam
Pour quelqu'un qui essaie juste de revenir jouer avec C ++ cinq ans après l'université, c'est l'une des meilleures réponses.
Panzercrisis
10

Le compromis est

char * p;

K&R utilise

char *p;

C'est à vous de décider sauf si vous suivez une norme de codage - dans ce cas, vous devez suivre ce que tout le monde fait.

jnnnnn
la source
4
J'ai appris à mes dépens que char * x, y ne signifie pas que y est un char *. Maintenant, je peux voir pourquoi K&R suit ce style.
Rahul Kadukar
qu'est-ce que K&R et pourquoi est-ce important ce qu'une seule source de code utilise? J'utilise char* p;. c'est une question de style, pas de convention ou de règles. pour moi, il est plus logique que p soit de type char*, donc évidemment le * devrait être avec le type.
FalcoGer
@FalcoGer J'ai ajouté un lien pour K&R. Peu importe ce qu'une seule source de code utilise. Votre équipe pourrait être ennuyée contre vous si vous ne suivez pas leurs normes, car vous les faites travailler plus dur pour comprendre votre code. Ces jours-ci, j'espère que les équipes utilisent de clang-formattoute façon.
jnnnnn
2

C'est une question de préférence, personnellement sur les projets que je vois le char * J'ai tendance à déclarer plusieurs pointeurs sur des lignes séparées. Il n'y a pas de véritable façon «correcte» de faire cela et tout se résume à la préférence. Certains disent qu'il est plus facile de lire (a) tandis que d'autres disent que (b) est plus facile de déclarer plus de variables du même type sur la même ligne.

Je trouve que (b) est plus courant, et dans certains cas, j'ai vu

char * a;

ou quelque chose comme ça. Encore une fois la préférence. Peu importe ce avec quoi vous êtes à l'aise ou quel que soit le projet sur lequel je travaille, j'utiliserai (sauf si je l'écris moi-même, auquel cas j'utilise (a))

Jésus Ramos
la source