Comment fonctionne exactement l'opérateur?: En C?

10

J'ai une question, comment le compilateur fonctionne sur le code suivant:

#include<stdio.h>

int main(void)
{
  int b=12, c=11;
  int d = (b == c++) ? (c+1) : (c-1);
  printf("d = %i\n", d);
}

Je ne sais pas pourquoi le résultat est d = 11.

J0S
la source
1
Pourquoi n'êtes-vous pas sûr? À quoi d'autre vous attendriez-vous et pourquoi?
Gerhardh
2
Je ne me souviens pas de la sémantique précise impliquée, mais vous observez peut-être un comportement indéfini.
chepner
3
Non, @chepner, il y a un point de séquence après avoir évalué l'état d'un ternaire, avant d'évaluer l'alternative sélectionnée. Cela évite le vecteur UB, je suppose que vous pensez.
John Bollinger
Ouais, je ne sais pas où je pensais que le compilateur aurait le choix.
chepner

Réponses:

6

Dans int d = (b == c++) ? (c+1) : (c-1);:

  • La valeur de c++est la valeur actuelle de c, 11. Séparément, cest incrémenté à 12.
  • b == 11est faux, car best 12.
  • Puisque (b == c++)c'est faux,(c-1) est utilisé. De plus, l'incrémentation de cà 12 doit être terminée à ce stade.
  • Depuis c12 ans, c-1c'est 11.
  • d est initialisé à cette valeur, 11.
Eric Postpischil
la source
5

Selon la norme C (6.5.15 Opérateur conditionnel)

4 Le premier opérande est évalué; il y a un point de séquence entre son évaluation et l'évaluation du deuxième ou du troisième opérande (celui qui est évalué). Le deuxième opérande n'est évalué que si le premier est différent de 0; le troisième opérande n'est évalué que si le premier est égal à 0; le résultat est la valeur du deuxième ou du troisième opérande (celui qui est évalué), converti dans le type décrit ci-dessous. 110)

Donc, dans l'expression d'initialisation de cette déclaration

int d = (b == c++) ? (c+1) : (c-1);

la variable best comparée à la valeur de la variable ccar l'opérateur de post-incrémentation renvoie la valeur de son opérande avant de l'incrémenter.

Comme les valeurs ne sont pas égales les unes aux autres ( best définie sur 12 tandis qu'elle cest définie sur 11), la sous-expression (c-1)est évaluée.

Selon la citation, il y a un point de séquence après l'évaluation de la condition de l'opérateur. Cela signifie qu'après évaluation de la condition ca la valeur 12après avoir appliqué l'opérateur post-incrément à la variable c. Par conséquent, la variable d est initialisée par la valeur 1( 12 - 1).

Vlad de Moscou
la source
2
La seule réponse correcte - ce cas spécifique doit être répondu en mentionnant le point de séquence dans ?:. Parce que normalement en C, la combinaison ++avec d'autres opérations sur le même opérande est un comportement non défini. Et ce code ne fonctionne que de manière prévisible car il ?:a diverses règles spéciales de flocon de neige.
Lundin
4

Beacuse la condition est fausse, donc le falsecas se produira :, c-1mais puisque vous avez incrémenté cla condition par c++, cc'est maintenant 12. Le résultat est donc 12 - 1 qui est 11.

EDIT: L'OP a mal compris l'incrément de poste.

Donc, ce qui se passe réellement est comme ceci:

#include<stdio.h>
int main(void)
{
  int b=12, c=11;
  int d;

  if (b == c) { // 12 == 11 ? -> false
    c = c + 1;
    d = c + 1;
  } else { // this executes since condition is false
    c = c + 1; // post increment -> c++ -> c = 12 now
    d = c - 1; // 12 - 1 = 11 -> d = 11
  }
  printf("d = %i\n", d);
}
Eraklon
la source
1
Je pense que le PO fait référence à l'ordre des opérations, étant donné c++l'état de la situation. La condition est fausse, mais la orginal valeur cest utilisée pour calculer c - 1, pas la version incrémentiels.
chepner
1
Je pensais que sincce 12 == 11 + 1 c'est vrai ...
J0S
Mais ce n'est pas vrai puisque la nouvelle valeur c est utilisée ou est-ce que je manque le vôtre?
Eraklon
Je pense qu'il pourrait y avoir un malentendu entre c++et++c
ChatterOne
@ N00b c++est l' opérateur post- incrément. La valeur de c++est 11, avec pour effet secondaire de faire c == 12. ++caurait la valeur de 12.
chepner
4

Traduit en une instruction if régulière, votre code ressemblerait à ceci:

int b=12, c=11;
int d;

if (b == c++)
   d = c+1;
else
   d = c-1;

L'indice ici est que c est incrémenté après vérification de la condition. Vous entrez donc dans l' elseétat mais c y a déjà la valeur 12.

Ulysse
la source
1

Voir Opérateur ternaire.

Syntaxe

état ? value_if_true: value_if_false

Vous avez donc écrit

int d = (b == c++) ? (c+1) : (c-1);

Dans cette situation, le résultat sera 11 car, après les vérifications, la valeur 'c' est augmentée (c + 1 = 12) et seulement après cela, elle définit la valeur 'd' comme c (12) -1 qui est 11.

Si vous avez utilisé, par exemple:

int d = (b == ++c) ? (c+1) : (c-1);

La valeur "c" serait augmentée avant de vérifier la déclaration, elle serait donc vraie et la valeur "d" serait c (12) +1, ce qui correspond à 13.

Neto Costa
la source