0

Here's my program:

 int main(void)
 {
  int i, j, k, m;
  i=-3, j=2, k=0;
  m = k++ && ++i && ++j;
  printf("%d, %d, %d, %d\n", i, j, k, m);
 return 0;
 }

The output of the program above is:

 -3 2 1 0 

But according to operator precedence table, ++ should have evaluated first I guess. I also tried putting parenthesis around them, but still the output remains same. I read somewhere that putting parenthesis around will make it evaluate first, no matter what.

Somebody, please make it clear, how it's evaluated. Thanks in advance.

SheetJS
  • 22,470
  • 12
  • 65
  • 75
1lastBr3ath
  • 334
  • 1
  • 9
  • 2
    Read [Behaviour of && in C programming language](http://stackoverflow.com/questions/18229657/behaviour-of-in-c-programming-language/18229763#18229763) – Grijesh Chauhan Oct 24 '13 at 04:39
  • What you are trying to do? What is 'm'? – KarSho Oct 24 '13 at 04:42
  • because `k = 0` so expression `k++ && ++i && ++j;` equivalent to `0 && ++i && ++j;`, `k++;` and `0 && ++i && ++j;` = `False` so `++j` and `k++` will not be evaluated . – Grijesh Chauhan Oct 24 '13 at 04:43
  • 1
    Also see [this](http://stackoverflow.com/questions/12980757/arithmetic-c-operators/). – devnull Oct 24 '13 at 04:44
  • Precedence doesn't have anything to do with execution order; it only affects how operator arguments are grouped. – user2357112 Oct 24 '13 at 04:47
  • 1
    Neither precedence nor parenthesis have anything to do with order of evaluation. Order of evaluation is defined (when it is defined) by sequencing, which is a completely different concept. Sequencing (or its absence) is an inherent property of operators, which cannot be changed by any parenthesis. – AnT stands with Russia Oct 24 '13 at 04:50
  • Yeah, I already know that. I mean, for example, if I write x=0; a= x + (x=4); Output will be a = 4 + 4 = 8 If I am not wrong. The expression inside parenthesis is evaluated first. So, why not in my program above? – 1lastBr3ath Oct 24 '13 at 08:48
  • @1lastBr3ath: No. In `a = x + (x=4)` the expression inside the `()` is not "evaluated first". In fact, `a = x + (x=4)` produces *undefined behavior* specifically because of sequencing problems present in that expression. It is not `a = 4 + 4` as you incorrectly believe. It is impossible to predict what will happen to `a` in `a = x + (x=4)`. It can be evaluated as `a = 0 + 4` or as `a = 4 + 4` or as `a = 253 + 128` or it can simply crash. The behavior is, again, undefined. – AnT stands with Russia Oct 25 '13 at 01:23
  • Okay. So, operator precedence just groups operands together, right? Evaluation of operands is not defined, except in cases of &&, ||, ?:, and comma operator which introduces sequence points, right? One more question, what is unspecified. I don't think it's undefined, and what is implementation defined? – 1lastBr3ath Oct 25 '13 at 03:59
  • @1lastBr3ath: That's correct. As for different kinds of behavior: http://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior – AnT stands with Russia Oct 25 '13 at 16:36

2 Answers2

4

What's happening here is short-circuiting. k++ evaluates to 0, which is false. Thus the entire boolean expression k++ && ++i && ++j is false, so ++i and ++j are never executed.

Claudiu
  • 224,032
  • 165
  • 485
  • 680
3

You are confusing precedence with order of evaluation. Precedence defined how the operands are grouped. The higher precedence of ++ makes the expression equivalent to:

m = (k++) && (++i) && (++j);

But the evaluation order is irrelevant. The shortcut circuit of && guarantees that its left-hand operand is evaluated first.

In general, most operator doesn't specify the order of evaluation, with four exceptions: logical AND &&, logical OR||, conditional operator ?: and comma operator ,.


As a concrete example of different order of evaluation:

Given int i = 0, the result of i + (i++) is unspecified, the compiler may evaluates i++ first, which modifies the value of i, the compiler may choose to evaluates i first. You should avoid expressions like these.

On the other hand, the result of i && (i++) is determined, as && ensures the left operand i is evaluated first, since it's zero, the right operand i++ is never evaluated.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Can you please tell me the exact difference with example? I always thoughto perators with higher precedence evaluate first :( – 1lastBr3ath Oct 24 '13 at 08:52
  • @1lastBr3ath I added an example, hope that's more clear to you. – Yu Hao Oct 24 '13 at 11:43
  • Is this also undefined? int main(void) { int x, y, z; x = y + z + 10 == (y = z = 0); printf("x = %d, y = %d, z = %d", x, y, z); return 0; } – 1lastBr3ath Oct 24 '13 at 14:57
  • @1lastBr3ath Possible using uninitialized variables, yes, it's undefined. – Yu Hao Oct 24 '13 at 15:00
  • int main() { int x = 2, y = 0; int z = (y++) ? 2 : y == 1 && x; printf("%d\n", z); return 0; } why is this program printing 1? Everything is defined here, I think. – 1lastBr3ath Oct 25 '13 at 14:43
  • @1lastBr3ath `y++` is evaluated first, result is `0` then `y` increments to `1`, then `z` takes the value of `y == 1 && x`, since `1 && x` is `1`, so `y == 1` is true, `z` is assigned `1`. – Yu Hao Oct 25 '13 at 14:53
  • Conditional operator operates from right-to-left, doesn't it? while && guarentees left-to-right operation, right? So, it should have evaluated as: z = (y++) ? (2) : ((y==1) && x) Where operating from right-to-left, ((y==1) && x) should be evaluated first, if I'm not wrong. Conditional operator also introduces a sequence point, doesn't it? Correct me, if I'm wrong. – 1lastBr3ath Oct 25 '13 at 14:58
  • 1
    @1lastBr3ath No, the conditional operator evaluates its first operand first, and then evaluates its second or third operand depending on if the fist value is non-zero or zero. Did you take the idea of `?:` operates from right to left because it's **right associate** ? – Yu Hao Oct 25 '13 at 15:06
  • Yup. So, what does it mean by "right associativity"? – 1lastBr3ath Oct 25 '13 at 15:10
  • 1
    @1lastBr3ath It's too big a topic to discuss in the comment. Basically, **precedence** decides the grouping of different operators, right? But actually some operators have the same precedence, e.g, binary `+` and `-`, **associativity** decides the grouping of operators with the same precedence. `1+2-3` is grouped as `(1+2)-3`, right? that's because`+` `-` are left associate. – Yu Hao Oct 25 '13 at 15:16