C - Инкремент не обновляет значение переменной - PullRequest
3 голосов
/ 26 января 2020

Я работаю над простой C программой, но столкнулся с некоторой путаницей. Ниже приведен код:

int main(void) {
  int i, j, k;
  i = 3;
  j = 4;
  k = 5;

  printf("%d ", i < j || ++j < k);
  printf("\n");  // LINE 1

  printf("%d %d %d", i, j, k);  // LINE 2

  return 0;
}

В приведенной выше программе переменная j начинается с 4. Затем в выражении printf строки 1 мы увеличиваем значение j на 1 (++ j = 5) ,

Теоретически, я бы предположил, что когда j печатается в printf (строка 2), оно печатается как 5, так как мы сделали приращение в строке 1 для j. Однако каждый раз, когда я запускаю код, в строке 2 выводится исходное значение j, которое было 4, а НЕ 5.

Что-то мне не хватает?

Ответы [ 5 ]

7 голосов
/ 26 января 2020

j никогда не увеличивается, потому что ++j никогда не оценивается. Оператор OR удовлетворяется, когда он впервые проверяет i < j.

3 голосов
/ 26 января 2020

Это пример оценки короткого замыкания. Когда логическое выражение равно A || B, если A истинно, нет необходимости оценивать B, и большинство языков придерживаются этого.

В этом случае i

1 голос
/ 26 января 2020

Глядя на это выражение:

i < j || ++j < k

Оператор преинкремента ++ имеет наивысший приоритет, за которым следует оператор меньше 100 *, за которым следует логический оператор ИЛИ ||. Таким образом, он анализируется следующим образом:

(i < j) || ((++j) < k)

Логический оператор ИЛИ || оценивается как true (в частности, значение 1), если либо левая сторона, либо правая сторона оценивается как true. Из-за этого у него также есть свойство, что правая сторона не будет оцениваться, если левая сторона оценивается как true, поскольку результат всего выражения уже известен в этой точке. Обычно это называется оценка короткого замыкания .

Такое поведение продиктовано разделом 6.5.14p3 C стандарта относительно логического оператора ИЛИ:

В отличие от побитового оператора |, оператор || гарантирует оценку слева направо ; если вычисляется второй операнд, между оценками первого и второго операндов существует точка последовательности. Если первый операнд сравнивается с неравным 0, второй операнд не оценивается.

Возвращаясь к выражению, i < j вычисляется первым. Значение i равно 3, а значение j равно 4, поэтому 3 < 4 оценивается как 1. Поскольку это значение левой стороны оператора ||, результат оператора || равен 1, а правая часть ++j < k не оценивается, поэтому j никогда не увеличивается.

0 голосов
/ 26 января 2020

Это хороший пример, чтобы узнать, что такое оценка короткого замыкания. В логическом выражении (i Вкратце разница между | и || это | рассмотрим оба условия, верно ли первое. Но || nevwr рассматривает или обрабатывает второе условие, если первое условие истинно и оно переходит на следующую строку.

0 голосов
/ 26 января 2020

Это называется оценкой короткого замыкания. Если i < j равно true, то ++j < k не будет оцениваться.

...