Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't ++i || ++j && ++k give the expected value

Tags:

c

I want to know why the value of k is 1 in the below code.

I think ++i || ++j && ++k is executed along the order:

((++i || ++j) && ++k)

So, in the first fragment, (++i || ++j), ++i is true, so ++j is not evaluated, so i=2, j=1. Next, in the second fragment, (true && ++k), so ++k is evaluated, and then k=2.

#include <stdio.h>

int main(void)
{
    int i, j, k;

    i = 1; j = 1; k = 1;
    printf("%d ", ++i || ++j && ++k);
    printf("%d %d %d\n", i, j, k);
    return 0;
}

But,

printf("%d %d %d\n", i, j, k);

shows

2 1 1

I don't know what was mistaken or what I've misunderstood.

like image 997
김재우 Avatar asked Apr 04 '19 14:04

김재우


2 Answers

The logical AND operator && has higher precedence than the logical OR operator ||. So the expression is actually parsed as:

++i || (++j && ++k)

++i evaluates to true so the entire right side of the ||, i.e. ++j && ++k, is not evaluated. This results in neither j nor k being incremented.

It can be difficult to remember all the precedence rules, both for yourself and for others who read your code. So when in doubt, use parenthesis to clarify your intentions.

like image 72
dbush Avatar answered Nov 12 '22 09:11

dbush


Running with compiler warnings, or a good editor like Atom.io, reveals the problem.

cc -Wall -Wshadow -Wwrite-strings -Wextra -Wconversion -std=c99 -pedantic -g `pkg-config --cflags glib-2.0`   -c -o test.o test.c
test.c:8:30: warning: '&&' within '||' [-Wlogical-op-parentheses]
    printf("%d ", ++i || ++j && ++k);
                      ~~ ~~~~^~~~~~
test.c:8:30: note: place parentheses around the '&&' expression to silence this warning
    printf("%d ", ++i || ++j && ++k);
                             ^
                         (         )
1 warning generated.

It's a precedence issue. Operators in an expression are not evaluated left-to-right but rather in precedence order. ++i || ++j && ++k is being evaluated as ++i || (++j && ++k) because && has a higher precedence than ||.

To avoid these issues, turn on compiler warnings and make it a habit to put parens around anything that might be ambiguous.

like image 4
Schwern Avatar answered Nov 12 '22 08:11

Schwern