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.


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.

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).


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);
}

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.


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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.