-1
votes

Un exemple spécifique de court-circuit en C

Je comprends le concept de base du court-circuit avec les opérateurs, mais pourquoi

int i = 0, j = -1, k = 1, m;
m = !(i++ && ++j) || ++k;
printf("%d %d %d %d", i, j, k, m);

avoir 1 -1 1 1 comme sortie? Plus précisément, pourquoi j == -1 au lieu de 0?

Je sais que des questions similaires ont déjà été posées, mais je ne comprends pas cet exemple précis que je n'ai trouvé nulle part.


14 commentaires

Pourquoi j devrait-il être j à 0?


i++ est faux, donc la conjonction && est fausse et ++j n'est pas évalué.


++ j est évalué comme -1 + 1 = 0? J'ai l'impression d'avoir fait une erreur évidente dans ma pensée


Le post-incrément i++ renvoie la valeur d'origine de i (avant l'incrément) qui est zéro. Ainsi, la partie après && n'est pas évaluée (à cause d'un raccourci).


@dxiv: vous voulez dire que i est faux, donc i && ... n'est pas évalué, et ainsi de suite.


oh jésus, je me sens si stupide maintenant. Je regardais ce problème pendant environ 10 minutes sans me rendre compte que j'avais évalué i ++ comme ++ i dans ma tête. Edit: suppose que je suis fatigué comme l'enfer, hein


@DavidIlic: pouvez-vous compiler ceci en code ASM, pour que nous puissions y jeter un coup d'œil?


@Dominique Je voulais dire l'expression i++ qui vaut 0 .


Merci les gars, je comprends ce qui se passe maintenant. J'ai fait une erreur dans ma tête


@dxiv: i est égal à 0, donc i && ... n'est pas évalué, et i++ n'est pas évalué, ou comment i++ peut-il être 0 si i est 0?


@Dominique Bien sûr, i++ est évalué, comment le compilateur pourrait-il déterminer autrement la valeur de la conjonction. Ceci est cohérent avec la valeur de OP de 1 pour i après l'évaluation.


@dxiv: dans sa réponse, Pmg déclare que i = -1 , d'où cela vient-il?


@Dominique Cela a été utilisé comme exemple dans la réponse de pmg. Le message d'OP montre i == 1 sur la dernière ligne.


Cela semble être une bonne raison de ne pas écrire de code comme celui-ci.


3 Réponses :


1
votes
i = -1;
i++;         // value of expression is -1
             // side effect is changing i to 0
if (i++) ;   // value of `i++` is zero; the if will not "trigger"

i = 0;
if (i++ && foo) ; // i++ has value of zero (false)
                  // so false && <anything> is false
                  // so foo is not evaluated

3 commentaires

Oui, je comprends maintenant. Merci


Je n'ai pas: pourquoi i - i égal à -1?


Je l'ai fait -1 pour l'exemple, pour ne pas avoir à le rendre 0 deux fois.



1
votes

La valeur de l'opérateur d'incrémentation postfixe est la valeur de son opérande avant l'incrémentation.

La valeur de l'expression i ++ est donc égale à 0 car la variable i a été initialisée par 0.

Donc, comme la valeur de la sous-expression i++ est 0 alors la sous-expression ++j dans cette expression

m = !(i++ && ++j) || ++k;

n'est pas évaluée et la valeur de l'expression elle-même est 0 .

Application de l'opérateur de négation

!(i++ && ++j) || ++k

vous obtiendrez 1 (vrai logique). Donc la sous-expression ++k de l'expression

!(i++ && ++j)

ne sera pas évalué.

En conséquence, la valeur de l'expression entière est égale à 1 qui est affectée à la variable m .

(i++ && ++j)

Par contre, comme il a été souligné au début, l'expression i++ été évaluée. Donc, après cette déclaration, i serai égal à 1 .


0 commentaires

1
votes

int i = 0, j = -1, k = 1, m;

!(i++ && ++j) || ++k; ==> seul i++ sera évalué, j et k ne seront pas évalués

disons simplement que nous substituons les valeurs des variables, puis l'expression devient comme ci-dessous.

!(0 && ++ -1) || ++1

étape 1 !(0 && ++ -1) ==> pour l'opérateur && si l'opérande du côté gauche est faux alors nous n'avons pas besoin de vérifier l'opérande du côté droit, donc -1 ne sera pas incrémenté, donc la valeur de j sera -1 lui-même.

et donc l'expression du côté gauche avant || devient !(0)

étape 2 !(0) || ++1

maintenant !(0) sera 1, donc pour || opérateur si l'opérande du côté gauche est VRAI, alors pas besoin d'aller pour l'opérande du côté droit, alors ++k ne sera pas exécuté.

m = 1 || ++1 ==> 1

puisque seul i++ est évalué, il changera sa valeur en 1 donc la sortie est: 1 -1 1 1


0 commentaires