La bonne réponse est: le code produit un comportement indéfini.
La raison pour laquelle le comportement est indéfini, c'est que les deux expressions ++x
et x + 1
sont en modifiant x
et de la lecture x
pour une autre (pour modification) de la raison et de ces deux actions ne sont pas séparés par un point de séquence. Il en résulte un comportement non défini en C (et C++). L'exigence est donné à 6.5/2 de la norme du langage C.
Notez que le comportement non défini dans la présente affaire n'a absolument rien à voir avec le fait qu' printf
de la fonction est donné qu'un spécificateur de format et de deux arguments. Pour donner plus d'arguments pour printf
qu'il y a des spécificateurs de format dans la chaîne de format est parfaitement légal dans C. de Nouveau, le problème est enraciné dans la violation de l'évaluation de l'expression des exigences de langage C.
Aussi, notez que certains participants de cette discussion ne parviennent pas à saisir le concept de comportement indéfini, et d'insister sur la mélanger avec la notion de comportement quelconque. Afin de mieux illustrer la différence considérons l'exemple simple suivant
int inc_x(int *x) { return ++*x; }
int x_plus_1(int x) { return x + 1; }
int x = 1;
printf("%d", inc_x(&x), x_plus_1(x));
Le code ci-dessus est "équivalent" à celui d'origine, sauf que les opérations qui impliquent x
sont enveloppés dans des fonctions. Ce qui va se passer dans ce dernier exemple?
Il n'y a pas un comportement non défini dans le présent code. Mais depuis que l'ordre d'évaluation des printf
arguments est indéterminée, ce code génère un comportement non spécifié, c'est à dire qu'il est possible qu' printf
sera appelé comme printf("%d", 2, 2)
ou printf("%d", 2, 3)
. Dans les deux cas, la sortie sera en effet 2
. Cependant, la différence importante de cette variante est que tous les accès à l' x
sont enveloppés dans la séquence des points présents au début et à la fin de chaque fonction, de sorte que cette variante ne permet pas de produire un comportement indéfini.
C'est exactement le raisonnement de certains autres affiches sont d'essayer de forcer sur l'exemple d'origine. Mais il ne peut pas être fait. L'exemple original produit non défini comportement, ce qui est totalement différent de la bête. Ils sont apparemment en train d'insister pour que, dans la pratique, un comportement indéfini est toujours équivalent à un comportement non spécifié. Ceci est totalement faux de prétendre que seuls indiquent le manque d'expertise dans ceux qui la font. Le code original produit un comportement indéfini, période.
Pour poursuivre l'exemple, nous allons modifier l'exemple de code précédent pour
printf("%d %d", inc_x(&x), x_plus_1(x));
la sortie de ce code deviendra généralement imprévisibles. Elle peut imprimer 2 2
ou elle peut imprimer 2 3
. A noter toutefois que même si le comportement est imprévisible, il ne produit toujours pas le comportement indéfini. Le comportement est indéterminé, peu pas indéfini. Un comportement non spécifié est limité à deux possibilités: soit 2 2
ou 2 3
. Un comportement indéfini n'est pas limité à quoi que ce soit. Il peut format de votre disque dur à la place de quelque chose d'impression. Sentez la différence.