Как именно работает оператор?: В 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.

J0S
источник
1
Почему ты не уверен? Что еще вы ожидаете и почему?
Герхард
2
Я не помню точную семантику, но вы можете наблюдать неопределенное поведение.
Чепнер
3
Нет, @chepner, есть точка последовательности после оценки состояния троичного, перед оценкой выбранной альтернативы. Это избегает вектора UB, я полагаю, вы думаете о.
Джон Боллинджер
Да, я не уверен, где я думал, что у компилятора будет выбор.
chepner

Ответы:

6

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

  • Значение c++является текущим значением c11. Отдельно cувеличивается до 12.
  • b == 11ложно, так bкак 12.
  • Так (b == c++)как ложно, (c-1)используется. Кроме того, увеличение cдо 12 должно быть завершено к этому моменту.
  • Так как cэто 12, c-1это 11.
  • d инициализируется до этого значения, 11.
Эрик Постпищил
источник
5

Согласно стандарту C (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);
}
Eraklon
источник
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, потому что после проверок if значение 'c' увеличивается (c + 1 = 12) и только после этого оно устанавливает значение d в качестве c (12) -1, которое равно 11.

Если вы использовали, например:

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

Значение «c» будет увеличено перед проверкой оператора, поэтому оно будет истинным, а значение «d» будет равно c (12) +1, что равно 13.

Нето Коста
источник