int i=5;
printf("%d",i+++++i);
这会产生错误,但是:
printf("%d",i+++i);
给出输出 11。在这种情况下,编译器将其读取为:
printf("%d",i+ ++i);
为什么在第一个表达式中没有这样做?IE :
printf("%d",i+++++i);
int i=5;
printf("%d",i+++++i);
这会产生错误,但是:
printf("%d",i+++i);
给出输出 11。在这种情况下,编译器将其读取为:
printf("%d",i+ ++i);
为什么在第一个表达式中没有这样做?IE :
printf("%d",i+++++i);
因为运算符优先级i++++++i
被视为(i++)++ + i)
. 这会产生编译器错误,因为(i++)
它不是左值。
i+++++i
被解析为i ++ ++ + i
。它包含无效的子表达式i ++ ++
。正式地说,这个表达式包含一个约束违反,这就是它不能编译的原因。
同时i+++i
被解析为i ++ + i
(而不是i + ++ i
您错误地认为的那样)。它不包含任何约束违规。它会产生未定义的行为,但格式正确。
此外,相信printf("%d",i+++i)
会打印是相当幼稚的11
。的行为i+++i
是未定义的,这意味着尝试预测输出是没有意义的。
根据语言规范,在两个序列点之间多次修改同一个变量是未定义的行为§6.5
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,应仅读取先验值以确定要存储的值。 (71)
71) 本段呈现未定义的语句表达式,例如
i = ++i + 1;
a[i++] = i;
同时允许
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…</p>
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 ++
.