Як саме працює оператор?: У C?


10

У мене виникає питання, як компілятор працює з таким кодом:

#include<stdio.h>

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

Я не знаю , чому результат d = 11.


1
Чому ви не впевнені? Чого б ви ще очікували і чому?
Герхард

2
Я не пригадую точної семантики, але ви можете спостерігати за невизначеною поведінкою.
чепнер

3
Ні, @chepner, перед оцінкою вибраної альтернативи є точка послідовності після оцінки стану трійки. Це дозволяє уникнути вектора UB, я думаю, ви думаєте.
Джон Боллінгер

Так, я не впевнений, де я вважав, що компілятор матиме вибір.
чепнер

Відповіді:


6

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

  • Значення c++поточного значення становить c11. Окремо cзбільшується до 12.
  • b == 11помилково, оскільки bце 12.
  • Оскільки (b == c++)є помилковим, (c-1)використовується. Також приріст cдо 12 повинен бути завершений цим пунктом.
  • Оскільки c12, c-1це 11.
  • d ініціалізується до цього значення 11.

5

Відповідно до стандарту С (6.5.15 умовний оператор)

4 Оцінюється перший операнд; між його оцінкою та оцінкою другого або третього операнду є точка послідовності (залежно від того, що оцінюється). Другий операнд оцінюється лише в тому випадку, якщо перший порівнює нерівне з 0; третій операнд оцінюється лише в тому випадку, якщо перший порівнюється рівним 0; Результатом є значення другого або третього операнда (залежно від того, що оцінюється), перетвореного у тип, описаний нижче.110)

Отже, в ініціалізуючому вираженні цієї декларації

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

змінна bпорівнюється зі значенням змінної, cтому що оператор після інкремента повертає значення свого операнда перед його збільшенням.

Оскільки значення не дорівнюють один одному ( bвстановлюється 12, тоді cяк встановлено 11), то під-вираження (c-1)оцінюється.

Згідно з цитатою, після оцінки стану оператора є пункт послідовності. Це означає, що після оцінки умови cмає значення 12після застосування оператора після збільшення до змінної c. В результаті змінна d ініціалізується значенням 1( 12 - 1).


2
Єдина правильна відповідь - на цей конкретний випадок слід відповісти, згадуючи пункт послідовності в ?:. Тому що зазвичай у C поєднання ++з іншими операціями над тим же операндом є невизначеною поведінкою. І цей код працює передбачувано лише тому, що в ньому ?:є різні спеціальні правила сніжинки.
Лундін

4

Оскільки умова є помилковою, тому falseвипадок трапиться: c-1але, оскільки ви зросли cв умові до c++, тому cзараз 12. Таким чином, результат 12 - 1, що дорівнює 11.

РЕДАКТУВАННЯ: ОП неправильно зрозуміло - збільшення посади.

Отже, що насправді відбувається так:

#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
Я думаю, що ОП посилається на порядок операцій, враховуючи c++умову. Умова хибна, але тоді для обчислення використовується початкове значення , а не нарощена версія. cc - 1
чепнер

1
Я думав, що sincce 12 == 11 + 1 це правда ...
J0S

Але це неправда, оскільки використовується нове значення c чи я пропускаю точку вашого?
Ераклон

Я думаю, що може виникнути непорозуміння між c++та++c
ChatterOne

@ N00b c++є пост -increment оператора. Значення c++11, з побічним ефектом виготовлення c == 12. ++cмав би значення 12.
чепнер

4

У перекладі на звичайний if-оператор ваш код виглядатиме так:

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

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

Розуміння тут полягає в тому, що c збільшується після перевірки умови. Отже, ви входите в elseстан, але c вже має значення 12.


1

Зверніться до термінального оператора.

Синтаксис

хвороба ? value_if_true: value_if_false

Отже, ви написали

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

У цій ситуації результат буде 11, оскільки після перевірки значення 'c' збільшується (c + 1 = 12) і лише після цього він встановлює значення 'd' як c (12) -1, що становить 11.

Якщо ви використовували, наприклад:

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

Значення "c" було б збільшено до перевірки твердження, тому було б істинним, а значення "d" було б c (12) +1, що становить 13.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.