Подтвердить что ты не робот

Почему "if (i ++ && (i == 1))" false, где я является int, сохраняющим значение 1?

{
    int i = 1;
    if (i++ && (i == 1))
        printf("Yes\n");
    else
        printf("No\n");
}

В соответствии с моим пониманием, в if, сначала будет вычисляться выражение (i==1), которое должно возвращать 1, а затем оно логически связано с 1, которое является значением i > , поэтому выражение должно возвращать 1 && 1 == 1, но выполняется else.

Может кто-нибудь объяснить, почему выполняется else часть?

4b9b3361

Ответ 1

Нет. В C есть точка последовательности между оценкой LHS оператора && и оценкой RHS, а приращение должно выполняются и выполняются до оценки RHS. Таким образом, выполняется i++ (эквивалентно i++ != 0), и инкремент завершается (и выражение оценивается как true), поэтому к моменту оценки RHS i == 2 и, следовательно, общее выражение ложно, и вы получите "Нет". Если LHS оператора && оценивается как false (0), RHS не будет оцениваться из-за свойства "короткого замыкания" оператора &&.

Только несколько операторов обладают свойством иметь точку последовательности между оценкой LHS и RHS: &&, || и , (как оператор, а не как разделитель в списке аргументов) - и там ? : тоже, который не является двоичным оператором, но имеет точку последовательности после вычисления условия и перед тем, как оценивается выражение после ? или выражение после : (из которого один или другой, но не оба, всегда оцениваются).

Операторы && и || являются единственными операторами с свойством "короткого замыкания". RHS && оценивается только в том случае, если LHS оценивается как true; RHS || оценивается только в том случае, если LHS оценивает значение false.


Уточнение в точках последовательности

Iwillnotexist Idonotexist правильно утвердил:

Стандарт C11 не покончил с точками последовательности, только стандарт С++ 11 сделал.

С++ 11 (ISO/IEC 14882: 2011) гласит:

1.9 Выполнение программы

¶13. Сегментированное ранее - асимметричное, транзитивное, парное отношение между оценками, выполненными одним (1.10), что вызывает частичный порядок среди этих оценок. При любых двух оценках A и B, если A секвенируется до B, тогда выполнение A должно предшествовать исполнению B. Если A не секвенировано до B и B не секвенированы до A, тогда A и B не подвержены влиянию. [Примечание: Выполнение непересекающихся оценки могут перекрываться. -end note] Оценки A и B неопределенно секвенированы, когда либо A секвенируется до того, как B или B секвенированы до A, но не указано, что. [Примечание: неопределенно секвенированные оценки не могут пересекаться, но либо могут быть выполнены в первую очередь. -end note]

Термин "точка последовательности" вообще не отображается в С++ 11 (единственное совпадение - "указатель последовательности" ).

C11 (ISO/IEC 9899: 2011) гласит:

5.1.2.3 Выполнение программы

¶3. Сегментированное ранее - асимметричное, транзитивное, парное отношение между оценками выполненный одним потоком, который вызывает частичный порядок среди этих оценок. При любых двух оценках A и B, если A секвенирован до B, то выполнение A предшествует исполнению B. (Наоборот, если A секвенировано до B, то B является последовательность после A.) Если A не секвенируется до или после B, то A и B являются unsequenced. Оценки A и B неопределенно секвенированы, когда A секвенирован либо до, либо после B, но не указано, что. 13). Наличие точки последовательности между оценкой выражений A и B следует, что каждое вычисление значения и побочный эффект, связанный с А, секвенирован перед вычислением каждого значения и побочным эффектом связанных с B. (Краткое описание точек последовательности приведено в приложении C.)

13) Выполнение неэфференцируемых оценок может чередовать. Неопределенно упорядоченные оценки не может перемежаться, но может выполняться в любом порядке.

Итак, C11 сохраняет точки последовательности, но добавляет "секвенированные ранее" и связанные термины, используя, по существу, ту же терминологию, что и С++ 11.

Ответ 2

Здесь простое объяснение

enter image description here

и почему это условие становится "ложным"

Ответ 3

Когда в выражении используется &&, его аргументы гарантированно оцениваются слева направо. Таким образом, i будет иметь значение 2 при оценке (i==1). Следовательно, выражение ложно, и часть else будет выполнена.

Однако обратите внимание на полноту, что если левый аргумент оценивается как false или 0, то правильный аргумент вообще не оценивается.

Ответ 4

Я думаю, что 1 & 1 = 1 и 1 & 0 = 0 ясно для вас. Майкл Л ответ кажется мне хорошим. Но все же я попытаюсь немного разобраться. Вот ссылка, которая предоставляет список приоритетов операторов:

http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

Если вы перейдете по этой ссылке и обратитесь к этой таблице, вы узнаете, что && ушел в правую ассоциативность. Поэтому сначала я становлюсь 2 ПОСЛЕ левой части (Sruit попытался показать эту диаграмму), а затем для правой части я == 1 проверка выполнена. Мы можем проверить это, написав код, подобный приведенному ниже:

Этот код объясняет, что я = 2, когда поток выполнения достигает я == 1.

#include <stdio.h>
int main() {

    int i = 1;
    if (i++ && (printf("%d\n",i)))
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

Таким образом, выход:

2

Да

Итак, 2 == 1 оказывается ложным, и в конечном итоге ответ вызывает удивление! Правая боковая скобка дает 0 и левую сторону 1, так что 1 && 0 = 0. Я думаю, что это достаточно справедливо, чтобы понять.

Ответ 5

Вы запутались, потому что в операторе цикла я ++ используется для приращения постов. например.

for (i=0;i<1;i++)

В приведенной выше программе цикла i сначала получит начальное значение и условие проверки. Условие if истинно, поэтому он увеличивает i и оценивает i старое значение для тела цикла, но вне тела цикла имеет новое значение 1.

В вашем вопросе вы используете if, а область старого значения i закончится, когда он встретит логически оператор, автоматически получит новое значение и увеличится до 2, чтобы условие вернуло false.