Tal Dokhanian
Tal Dokhanian

Reputation: 33

C bitwise precedence and associativity

#include <stdio.h>

int main() {
    int a = 1;
    int b = a || (a | a) && a++;
    printf("%d %d\n", a, b);
    return 0;
}

when I ran this code the results were 1 and 1.

According to the C language Operator Precedence the operation && is supposed to happen before the operation ||. So shouldn't the result be 2 1 ? (a = 2, b = 1)

Upvotes: 2

Views: 92

Answers (3)

chqrlie
chqrlie

Reputation: 145287

When applying the operator precedence rules, the expression is equivalent to:

int b = a || ((a | a) && a++);

The evaluation or the operands to || and && is performed from left to right and shortcut evaluation prevents evaluating the right operand if the left operand can determine the result: since a is non zero, a || anything evaluates to 1 without evaluating the right operand, hence bypassing the a++ side effect.

Therefore both a and b have value 1 and the program prints 1 1.

Conversely, if you had written int b = (a || ((a | a)) && a++;, the left operand of && would have value 1, so the right operand need to be evaluated. a++ evaluates to 1 but increments a, so b have final value 1 and a is set to 2, producing your expected result.

The confusion comes from equating operator precedence with order of evaluation. These are two separate notions: operator precedence determines the order in which to apply the operators, but does not determine the order of evaluation of their operands.

Only four operators have a specified order of evaluation of their operands: &&, ||, ? : and , and the first 2 may skip evaluation of one, depending on the value of the other operand and the third only evaluates the first and only one among the second and third operands. For other operators, the order of evaluation of the operands is unspecified, and it may differ from one compiler to another, one expression to another or even one run to another, although unlikely.

Upvotes: 2

do thuan
do thuan

Reputation: 475

When I try to put a || (a | a) into a parenthesis. The result was as you expected.

So I guess that when C compiler executes an OR operator and it get a True value to the OR, the execution will finish immediately.

In your case, when the compiler executed the a || (a | a) (1 || something) operation. Value of b will be declared to 1 right away and a++ operator won't be execute.

Upvotes: 0

user3629249
user3629249

Reputation: 16540

when OR'ing expressions in C, a shortcut is taken, I.E. as soon as an expression is evaluated to TRUE, the rest of the OR'd expressions are not evaluated

The first expression a evaluates to TRUE, so all the rest of the expressions are not evaluated, so a is never incremented

Upvotes: 4

Related Questions