C Operators and Precedence

210 views Asked by At

I'm using C language, for the below code:

#include <stdio.h>

int main(int argc, char const *argv[])
{
    int num1=0;

    int res = ++num1 && num1++;

    printf("%d\t%d\n",num1,res);    
}

In the above code I get output as 2 1. I think the output should be 2 0.

Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.

Please comment how is this statement getting executed.

In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence, but if that is true then according to the associativity rule again num1++ should be executed first(right to left) which should again lead to answer as 2 0.

3

There are 3 answers

0
Lundin On BEST ANSWER

Lots of misconceptions here. First of all, operator precedence states the order of parsing, not the order of execution. There are two related but different terms, operator precedence and order of evaluation.
See What is the difference between operator precedence and order of evaluation?.

Once you understand order of evaluation, the && operator specifically comes with well-defined sequencing, which isn't normally the case for C operators. It guarantees a left-to-right order of evaluation. C17 6.5.14/4:

Unlike the bitwise | operator, the || operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares unequal to 0, the second operand is not evaluated.

Normally, you wouldn't be able to wild and crazy things with the ++ operator mixed with other operators, but the above && rule makes it possible in this specific case.

See Why can't we mix increment operators like i++ with other operators? It explains sequencing/sequence points.


In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,

They don't, prefix ++ takes precedence over postfix (and other unary operators). So associativity does not apply.

0
John Bode On

Please correct me if wrong, to solve this statement, the num1++(0) would be executed first due to highest precedence and then ++num1(2) would be executed and then at last && will be preformed because it has the lowest precedence.

Precedence only controls which operators are grouped with which operands - it does not affect the order in which expressions are evaluated.

The &&, ||, ?:, and comma operator all force left-to-right evaluation - the left operand is fully evaluated (and any side effects applied) before the right operand. && and || both short circuit - for &&, the right operand will be evaluated only if the left operand is non-zero.

The unary (prefix) ++ operator yields the current value of the operand plus 1, so the result of ++num1 is 1. As a side effect the value in num1 is incremented. Since this result is non-zero, num1++ is also evaluated. The postfix ++ operator yields the current value of the operand, so the result of num1++ is 1. As a side effect the value in num1 is incremented.

The result of an && expression is 1 if both operands are non-zero, 0 otherwise.

It's roughly equivalent to writing

tmp = num1 + 1;
num1 = num1 + 1;

res = 0;
if ( tmp != 0 )
{
  if ( num1 != 0 )
  {
    res = 1;
  }
}
num1 = num1 + 1;

So the result of ++num1 && num1++ is 1, and the value stored in num1 at the end of it is 2.

In some of the tutorials I find that postfix ++ and prefix ++ have the same precedence,

That is very wrong and you should stop using those tutorials immediately. Postfix operators have higher precedence than unary operators - *a++ is parsed as *(a++), ++a[i] is parsed as ++(a[i]), etc. An expression like ++i++ would be parsed as ++(i++), but you can't write such an expression in C - the result of i++ isn't an lvalue and cannot be the operand of a unary ++ like that.

0
Vlad from Moscow On

In the expression used as an initializer

 int res = ++num1 && num1++;

there is a sequence point for the operator &&.

From the C Standard (6.5.13 Logical AND operator)

3 The && operator shall yield 1 if both of its operands compare unequal to 0; otherwise, it yields 0. The result has type int.

and

4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right evaluation; if the second operand is evaluated, there is a sequence point between the evaluations of the first and second operands. If the first operand compares equal to 0, the second operand is not evaluated.

At first the left operand of the operator is evaluated and as a result num1 will be equal to 1 due to the unary (prefix) increment operator. As the sub-expression is not equal to 0 then the second operand is evaluated. Its value is the value before incrementing that is 1. As this second operand is also unequal to 0 then the whole expression is evaluated to the logical true and its value is 1 (see the first quote from the C Standard).

This value 1 is assigned to the variable res while the variable num1 after the postfix increment will be equal to 2.

So you will have that after this declaration res is equal to 1 and num1 is equal to 2.