int i=5;
printf("%d",i+++++i);
This gives error, but:
printf("%d",i+++i);
gives the output 11. In this case, the compiler read it as:
printf("%d",i+ ++i);
Why is this not done in first expression? i.e :
printf("%d",i+++++i);
int i=5;
printf("%d",i+++++i);
This gives error, but:
printf("%d",i+++i);
gives the output 11. In this case, the compiler read it as:
printf("%d",i+ ++i);
Why is this not done in first expression? i.e :
printf("%d",i+++++i);
Because of operator precedence i++++++i
is treated as (i++)++ + i)
. This gives a compiler error because (i++)
is not an lvalue.
i+++++i
is parsed as i ++ ++ + i
. It contains an invalid subexpression i ++ ++
. Speaking formally, this expression contains a constraint violation, which is why it does not compile.
Meanwhile i+++i
is parsed as i ++ + i
(not as i + ++ i
as you incorrectly believe). It does not contain any constraint violations. It produces undefined behavior, but is otherwise well-formed.
Also, it is rather naive to believe that printf("%d",i+++i)
will print 11
. The behavior of i+++i
is undefined, meaning that there's no point in trying to predict the output.
Modifying the same variable multiple times between two sequence points is an Undefined Behavior according to §6.5
of language specifications
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.(71)
71) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
In printf("%d",i+++++i);
, the source text i+++++i
is first processed according to this rule from C 2011 (N1570) 6.4 4:
If the input stream has been parsed into preprocessing tokens up to a given character, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token…
This causes the lexical analysis to proceed in this way:
i
can be a token, but i+
cannot, so i
is the next token. This leaves +++++i
.+
and ++
can each be a token, but +++
cannot. Since ++
is the longest sequence that could be a token, it is the next token. This leaves +++i
.++
is the next token. This leaves +i
.+
can be a token, but +i
cannot, so +
is the next token. This leaves i
.i
can be a token, but i)
cannot, so i
is the next token.Thus, the expression is i ++ ++ + i
.
Then the grammar rules structure this expression as ((i ++) ++) + i
.
When i++
is evaluated, the result is just a value, not an lvalue. Since ++
cannot be applied to a value that is not an lvalue, (i ++) ++
is not allowed.
After the compiler recognizes that the expression is semantically incorrect, it cannot go back and change the lexical analysis. Th C standard specifies that the rules must be followed as described above.
In i+++i
, the code violates a separate rule. This is parsed as (i ++) + i
. This expression both modifies i
(in i ++
) and separately accesses it (in the i
of + i
). This violates C 2011 (1570) 6.5 2:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
This rule uses some technical terms: In i ++
, the effect of changing i
is a side effect of ++
. (The main effect is to produce the value of i
.) The use of i
in + i
is a value computation of the scalar object i
. And these two things are unsequenced, because the C standard does not specify whether producing the value of i
for + i
comes before or after changing i
in i ++
.