142 votes

Expressions de pointeur : *ptr++, *++ptr et ++*ptr

Récemment, je suis confronté à ce problème que je suis incapable de comprendre par moi-même.

Que signifient vraiment ces trois expressions ?

*ptr++
*++ptr
++*ptr

J'ai essayé Ritchie. Mais malheureusement, je n'ai pas pu suivre ce qu'il a dit à propos de ces 3 opérations.

Je sais qu'elles sont toutes effectuées pour incrémenter le pointeur/la valeur pointée. Je suppose aussi qu'il peut y avoir beaucoup de choses à propos de la précédence et de l'ordre d'évaluation. Comme l'un incrémente le pointeur d'abord puis récupère le contenu de ce pointeur, l'autre récupère simplement le contenu puis incrémente le pointeur, etc. Comme vous pouvez le voir, je n'ai pas une compréhension claire de leurs opérations réelles, que j'aimerais éclaircir dès que possible. Mais je suis vraiment perdu lorsque j'ai l'occasion de les appliquer dans des programmes. Par exemple :

int main()
{
    char *p = "Hello";
    while(*p++)
         printf("%c",*p);
    return 0;
}

me donne cette sortie :

ello

Mais je m'attendais à ce qu'il imprime Hello . Une dernière demande - Veuillez me donner des exemples de comment chaque expression fonctionne dans un extrait de code donné. Car la plupart du temps, seule une simple théorie me dépasse.

6 votes

Vous avez manqué le quatrième : (*ptr)++ (les parenthèses sont nécessaires pour lever l'ambiguïté avec *ptr++)

15 votes

Parce que vous avez incrémenté le pointeur avant de l'imprimer. Vous vouliez while(*p) et printf("%c", *p++);

0 votes

Super questions pour l'interview. Utilisation pratique limitée. J'aimerais que le langage C n'ait pas ces pointeurs :)

45voto

nickie Points 3226

Suppose ptr points to the i-th element of array arr.

  1. *ptr++ évalue à arr[i] et place ptr pour pointer vers le (i+1)-ème élément de arr. C'est équivalent à *(ptr++).

  2. *++ptr place ptr pour pointer vers le (i+1)-ème élément de arr et évalue à arr[i+1]. C'est équivalent à *(++ptr).

  3. ++*ptr augmente arr[i] de un et évalue à sa valeur augmentée; le pointeur ptr reste inchangé. C'est équivalent à ++(*ptr).

Il y en a un autre, mais vous auriez besoin de parenthèses pour l'écrire:

  1. (*ptr)++ augmente arr[i] de un et évalue à sa valeur avant l'augmentation; le pointeur ptr est à nouveau laissé inchangé.

Le reste, vous pouvez le découvrir vous-même; la réponse a également été donnée par @Jaguar.

14voto

Jaguar Points 8451

*ptr++ : incrément postérieur un pointeur ptr

*++ptr : Pré-incrementer un pointeur ptr

++*ptr : pré-incrémenter la valeur à l'emplacement ptr

Lire ici sur les opérateurs d'incrémentation préfixe et suffixe


Cela donnera Hello comme sortie

int main()
{
    const char *p = "Hello";
    while(*p)
         printf("%c",*p++);//Incrémenter le pointeur ici
    return 0;
}

0 votes

@Nik-Lz Oui, la sortie serait Hello

7voto

nouney Points 2643

La condition dans votre boucle est mauvaise :

while(*p++)
    printf("%c",*p);

Est la même que

while(*p)
{
    ++p;
    printf("%c",*p);
}

Et c'est faux, cela devrait être :

while(*p)
{
    printf("%c",*p);
    ++p;
} 

*ptr++ est la même chose que *(ptr++), ce qui est :

const char  *ptr = "exemple";
char  value;

value = *ptr;
++p;
printf("%c", value); // affichera 'e'

*++ptr est la même chose que *(++ptr), ce qui est :

const char  *ptr = "exemple";
char  value;

++p;
value = *ptr;
printf("%c", value); // affichera 'x'

++*ptr est la même chose que ++(*ptr), ce qui est :

const char  *ptr = "exemple";
char  value;

value = *ptr;
++value;
printf("%c", value); // affichera 'f' ('e' + 1)

0 votes

Je suis tout à fait d'accord avec la première partie de la réponse. Dans la seconde partie, l'initialisation des pointeurs (vers des entiers !) avec des entiers est confuse pour quelqu'un qui peine à comprendre l'utilisation des pointeurs.

4voto

gman Points 9074

Je vais ajouter mon point de vue car bien que les autres réponses soient correctes, je pense qu'elles manquent quelque chose.

 v = *ptr++

signifie

 temp = ptr;
 ptr = ptr + 1
 v = *temp;

Alors que

 v = *++ptr

signifie

 ptr = ptr + 1
 v = *ptr

Il est important de comprendre que l'incrémentation postérieure (et la décrémentation postérieure) signifie

 temp = ptr       // Temporaire créé ici!!!
 ptr = ptr + 1   // ou - 1 en cas de décrémentation)
 v = *temp     // Temporaire détruit ici!!!

Pourquoi est-ce important? Eh bien en C ce n'est pas si important. En C++ cependant ptr pourrait être un type complexe comme un itérateur. Par exemple

 for (std::set::iterator it = someSet.begin(); it != someSet.end(); it++)

Dans ce cas, car it est un type complexe it++ peut avoir des effets secondaires en raison de la création de temp. Bien sûr, si vous avez de la chance, le compilateur essaiera de jeter le code qui n'est pas nécessaire, mais si le constructeur ou le destructeur de l'itérateur fait quelque chose, alors it++ montrera ces effets lorsqu'il crée temp.

En résumé, ce que j'essaie de dire c'est Écrivez ce que vous voulez dire. Si vous voulez dire incrémenter ptr alors écrivez ++ptr et non ptr++. Si vous voulez dire temp = ptr, ptr += 1, temp alors écrivez ptr++

4voto

Nobilis Points 3511

Vous avez raison concernant la priorité, notez que l'opérateur * a priorité sur l'incrémentation préfixée, mais pas sur l'incrémentation postfixée. Voici comment cela se décompose :

*ptr++ - en allant de gauche à droite, déréférencer le pointeur, puis incrémenter la valeur du pointeur (pas ce qu'il pointe, en raison de la priorité du postfixe sur le déréférencement)

*++ptr - incrémenter le pointeur puis le déréférencer, ceci est dû au fait que le préfixe et le déréférencement ont la même priorité et donc sont évalués dans l'ordre de droite à gauche

++*ptr - similaire au cas précédent en termes de priorité, encore une fois en allant de droite à gauche pour d'abord déréférencer le pointeur et ensuite incrémenter ce à quoi le pointeur pointe. Veuillez noter que dans votre cas, cela entraînera un comportement indéfini car vous essayez de modifier une variable en lecture seule (char* p = "Hello";).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X