Pourquoi * p ++ est-il différent de * p + = 1?

Considérer:

void foo1(char **p) { *p++; } void foo2(char **p) { *p += 1; } 

et

 char *s = "abcd"; char *a = s; foo1(&a); printf("%s", a); //abcd 

mais si j’utilise foo2() au lieu de:

 char *a = s; foo2(&a); printf("%s", a); //bcd 

Quelqu’un peut-il l’expliquer?

La clé est la priorité de l’opérateur += et ++ . Le ++ a une priorité plus élevée que le += (en fait, les opérateurs d’affectation ont la deuxième priorité la plus basse en C), donc l’opération

 *p++ 

signifie dereference du pointeur, puis incrémente le pointeur lui-même de 1 (comme d’habitude, selon les règles de l’arithmétique du pointeur, ce n’est pas nécessairement un octet, mais plutôt sizeof(*p) ce qui concerne l’adresse résultante). D’autre part,

 *p += 1 

signifie incrémenter la valeur pointée par le pointeur de un (et ne rien faire avec le pointeur lui-même).

Priorité. Le postfix ++ se lie plus étroitement que le préfixe * donc il s’incrémente p . Le += est à l’extrémité inférieure de la liste de priorité, avec l’opérateur d’affectation simple, de sorte qu’il ajoute 1 à *p .

La priorité du préfixe ++ et * est la même. L’associativité des deux est juste à gauche. La priorité de postfix ++ est supérieure à la fois à * et au préfixe ++. L’associativité de postfix ++ est de gauche à droite.

Commençons par *p += 1

Je vais essayer de répondre à un angle différent … Etape 1 Regardons les opérateurs et les opérandes: Dans ce cas, il s’agit d’un opérande (le pointeur p), et nous avons deux opérateurs, dans ce cas * pour déréférencer et + = 1 pour l’incrément. L’étape 2 qui a la priorité la plus élevée * a une priorité supérieure à + =


*P++ Celui-ci est un peu plus compliqué … peut-être même méchant Encore une fois, nous avons un opérande (p le pointeur) et deux opérateurs, seulement maintenant le * pour dereference et ++ post increment sont de la même priorité. (Dans certaines tables, le ++ dans une publication est une priorité plus élevée.)

Etape 1 Regardons les opérateurs et les opérandes: Dans ce cas, c’est l’opérande, et vous avez deux opérateurs, dans ce cas * pour le déréférencement et ++ pour l’incrément. Étape 2 qui a la priorité la plus élevée? ++ a la plus haute priorité sur * Note: même s’ils ont la même préséance qu’ils associent de droite à gauche, encore une fois, le ++ est avant * Étape 3 (la partie délicate …) Où est ++? c’est dans le côté droit de l’opérande, ce qui signifie Incrémentation POST Dans ce cas, le compilateur prend une “note mentale” pour effectuer l’incrément APRÈS que ce soit fait avec tous les autres opérateurs … Que signifie après? Cela signifie qu’il n’appliquera l’incrément que comme le tout dernier pas avant le suivant »; il sera donc fait avec tous les autres opérateurs qui sont sur la même note ‘line’: si c’était * ++ p alors il le fera AVANT tout autre opérateur sur la même ligne, donc dans ce cas, cela équivaut à prendre deux du registre du processeur, l’un contiendra la valeur du dereferenced * p et l’autre contiendra la valeur du p ++ incrémenté, la raison dans ce cas, il y en a deux, est l’activité POST … C’est ici que dans ce cas c’est délicat et ça ressemble à une contradiction. On s’attendrait à ce que ++ prenne le dessus sur le *, ce qui est le cas, mais que le POST signifie qu’il ne sera appliqué qu’après TOUS les autres opérandes, AVANT le prochain ‘;’ jeton…

Comme je l’ai dit, la partie délicate est que tout incrément à droite d’un opérande sera mis de côté et sera appliqué comme dernière opération avant de passer à la ligne suivante …