请问为什么下面代码输出的值为22?
求给出分析过程
#include<stdio.h>
int main(void)
{
int i=5,j=5;
int p;
p=(++i)+(++i)+(++i);
printf("p=%d",p);
return 0;
}
阿神2017-04-17 15:33:45
In an expression, the evaluation order of multiple ++ for the same variable is uncertain. This behavior is undefined. Different compilers may produce different results. It is recommended to write such code with side effects.
For the evaluation order, please refer to wiki
怪我咯2017-04-17 15:33:45
If this is an exam question, please refer to the relevant exam materials.
The correct ideas for C++11/14 and C11 are given here:
The relevant ordering rules for expression (++i)+(++i)+(++i)
are the increment-first ordering rule (side effects are calculated before the value) and the ordering rule for operators (the value of the operand is calculated before the value of the operator result is calculated).
The calculation order that can be determined by this: In this expression, the side effects and values of any ++i
are calculated before the value of the related +
is calculated (+
has no side effects) and its side effects are calculated before the value ( That is, increase first). According to the associativity of +
(from left to right), it can be concluded that the value of the first +
is calculated before the value of the second +
is calculated.
Undeterminable calculation order: There is no definite sequence relationship between the value calculation and side effects of any two ++i
.
So intuitively, a series of possible calculation processes can be listed based on the above restrictions:
6+7+8 = 13+8
6+8+7 = 14+7
7+6+8 = 13+8
...
But the problem is that the C++11/14 standard has the following convention:
(§1.9/15)[...]If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object , the behavior is undefined.
The C11 standard has the following conventions:
(§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.[...]
And because the order of side effects between any two '++i's in this expression is undetermined, this is undefined behavior in C++11/14 and C11.
The rules before C++11 and C11 will not be discussed here, but according to their standards, they are also undefined behavior.
The last wordy sentence is undefined behavior. The C++11 standard has the following conventions:
(§1.3.24) undefined behavior
behavior for which this International Standard imposes no requirements
[Note: Undefined behavior may be expected when this International Standard omits any explicit definition of behavior or when a program uses an erroneous construct or erroneous data. Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). Many erroneous program constructs do not engender undefined behavior; they are required to be diagnosed. — end note ]
The C11 standard has the following conventions
(§3.4.3)
1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).
That is to say, the standard does not make any requirements for the behavior of undefined behavior, and the compiler or running platform can agree on the behavior of undefined behavior at compile time or runtime, or not. Without convention, the behavior of the program will be completely unpredictable.
If you follow Tan Ye (Fog)’s idea: (probably) based on the combination of operator + (left combination), the equivalent expression ((++i)+(++i))+(++i)
is obtained. Then it is deduced that the two ++i
on the left are calculated first (heavy fog). Since they increase first, they are equivalent to (7+7)+(++i)
, which is equivalent to (7+7)+8
(big things), which is equal to 22
.
The problem is that the combination method has nothing to do with the order in which the values of the subexpressions are evaluated.
天蓬老师2017-04-17 15:33:45
The result of the first ++i participating in the operation is 6; the result of the second ++i participating in the operation is 7, making the first one also become 7; similarly, the result of the third participating in the operation is 8, so that the first two become 8, and the final result is 24. I am using VS, and this is measured with C++.
The same is VS, the result using C is as shown below
伊谢尔伦2017-04-17 15:33:45
The answer above is correct, so I have withdrawn the answer.
If you insist on struggling with this problem, you can compile the code into assembly for the compiler you are using and see what exactly happens
伊谢尔伦2017-04-17 15:33:45
Agree with @lianera’s answer: This kind of operation C language standard does not stipulate a unified order of operations.
PHPz2017-04-17 15:33:45
Um. . Having said so much, in fact, the problem is not at all about the calculation order. The order of addition operations is from left to right.
p=(++i)+(++i)+(++i);
When you add it for the first time, it looks like 6+7 at first glance. However, the self-increment of the second ++i makes the i(6) in front of it (the first ++i) also become 7.Then the sum of the first step is 14.
Then 14 plus the third i (8) equals 22.
This answer is limited to matching the SX textbook. In actual application, it will break his legs! Of course, different compilers will also give him expressions.