ProgrammationDéveloppeur C

Décrivez les différences entre les opérations d'incrémentation (i++) et (++i) dans le langage C. Quelle est leur sémantique, quand utiliser l'une ou l'autre et quels sont les dangers dans des expressions complexes ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Dans le langage C, les opérations d'incrémentation postfixe (i++) et préfixe (++i) augmentent la valeur de la variable de 1, mais la valeur retournée diffère :

  • i++ (postfixe) : renvoie d'abord la valeur actuelle, puis l'augmente.
  • ++i (préfixe) : augmente d'abord la valeur, puis renvoie la nouvelle valeur.

Exemple :

int i = 5; int a = i++; // a == 5, i == 6 int j = 5; int b = ++j; // b == 6, j == 6

Dans des expressions simples, la différence est insignifiante, mais dans des expressions complexes (par exemple, avec plusieurs incrémentations à la fois), un comportement indéfini peut se produire.

Question piège

Quelle sera la valeur de la variable a après l'exécution de l'expression int a = i++ + ++i;, si i = 1 ?

Réponse :

Le calcul dépend de l'ordre d'évaluation des opérandes, qui n'est pas garanti par la norme, et conduit également à un comportement indéfini, car la variable i est modifiée plus d'une fois entre l'utilisation successive de sa valeur. Ne faites pas cela !

Exemple de ce type de code :

int i = 1; int a = i++ + ++i; // comportement indéfini ! Ne le faites pas !

Exemples d'erreurs réelles dues à une méconnaissance des subtilités du sujet


Histoire

Dans un grand projet, le calcul de l'index dans un tableau était effectué comme arr[i++] = getValue(++i); — le développeur voulait conserver l'ancienne valeur tout en obtenant une nouvelle. Sur différents compilateurs, le comportement variait : parfois une valeur écrasait l'autre, parfois le programme plantait. La raison était les modifications multiples non autorisées de i dans une seule expression.


Histoire

Dans un projet embedded, la valeur du compteur était augmentée dans le cadre d'une expression complexe : if (buffer[i++] == TERMINATOR && ++i < SIZE) ... — sur le « matériel », un indice incorrect se produisait parfois en raison de l'ordre d'évaluation différent, conduisant à la lecture de données non initialisées.


Histoire

Lors du portage de code sur un autre compilateur, la différence dans l'implémentation de l'ordre d'évaluation des opérandes a conduit à un comportement imprévisible pour une boucle du type while (arr[i++] && i < MAX && arr[++i]). Le bogue n'a été détecté qu'à la suite de la phase de test sur le dispositif du client.