Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is "if (i++ && (i == 1))" false where i is an int holding the value 1?

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

As per my understanding, in the if condition, first the expression (i==1) will be evaluated which should return 1, and then it is logically anded with 1 which is the value of i, so the expression should return 1 && 1 == 1, but the else part is executed.

Can someone please explain why the else part is executed?

like image 396
Tahir Sanglikar Avatar asked Jul 12 '15 03:07

Tahir Sanglikar


People also ask

Why is if I were grammatically correct?

Many people use if I was and if I were interchangeably to describe a hypothetical situation. The confusion occurs because when writing in the past tense, I was is correct while I were is incorrect. However, when writing about non-realistic or hypothetical situations, if I were is the only correct choice.

Which is correct grammatically correct if I was or if I were?

A good trick to decide which you want to use is to determine if the thing you are talking about is something that actually happened or something that you are wishing or imagining might have happened. If it really happened, use “if I was,” but if not, go with “if I were.”

Can you use if I was you?

It is known as the subjunctive mood (from the grammatical point of view). Today you also find the phrase if I was you. Here Simple Past form of be is used. But there are people who say that this phrase is incorrect and would never use it (mainly Americans).


1 Answers

No. In C, there's a sequence point between the evaluation of the LHS of the && operator and the evaluation of the RHS, and the increment must take place and be completed before the RHS is evaluated. So, the i++ (equivalent to i++ != 0) is executed and the increment is completed (and the expression evaluates to true), so by the time the RHS is evaluated, i == 2 and hence the overall expression is false and you get 'No' printed. If the LHS of the && operator evaluated to false (0), the RHS would not be evaluated because of the 'short-circuit' property of the && operator.

Only a few operators have the property of having a sequence point between the evaluation of the LHS and RHS: &&, ||, and , (as an operator, not as a separator in an argument list) — and there's ? : too, which isn't a binary operator but which has a sequence point after the condition is evaluated and before either the expression after the ? or the expression after the : is evaluated (of which one or the other, but not both, is always evaluated).

The && and || operators are the only operators with the 'short-circuit' property. The RHS of && is only evaluated if the LHS evaluates to true; the RHS of || is only evaluated if the LHS evaluates to false.


Clarification on Sequence Points

Iwillnotexist Idonotexist correctly asserted:

The C11 standard hasn't done away with sequence points, only the C++11 standard did.

C++11 (ISO/IEC 14882:2011) says:

1.9 Program execution

¶13 Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread (1.10), which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [Note: The execution of unsequenced evaluations can overlap. —end note] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. —end note]

The term 'sequence point' does not appear in C++11 at all (the only near match is 'sequence pointer').

C11 (ISO/IEC 9899:2011) says:

5.1.2.3 Program execution

¶3 Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread, which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. (Conversely, if A is sequenced before B, then B is sequenced after A.) If A is not sequenced before or after B, then A and B are unsequenced. Evaluations A and B are indeterminately sequenced when A is sequenced either before or after B, but it is unspecified which.13) The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B. (A summary of the sequence points is given in annex C.)

13) The executions of unsequenced evaluations can interleave. Indeterminately sequenced evaluations cannot interleave, but can be executed in any order.

So, C11 does retain sequence points, but adds the 'sequenced before' and related terms using essentially the same terminology as C++11.

like image 124
Jonathan Leffler Avatar answered Sep 19 '22 15:09

Jonathan Leffler