多个++i(++i + ++i + ++i)连续相加的结果问题

问题:
如下示例程序:

#include<iostream.h>
void main()
{
 int i=5;
 int n = ++i + ++i + ++i;
 cout<<"n="<<n<<endl;
}

程序运行后输出结果为:n=22

这里的n=22是如何计算出来的?很多人都有这个疑问,因为很多人都会想结果应该是21(计算方式为:先计算所有的++i并返回值,再分别相加赋值给n)。
夜晚我们也在一起讨论了它,但也都说不出所以然来,后来通过讨论和查询资料对之有了一定的了解。

解释:

对于多个++i和i++连续计算,对不同的编译器来说计算方式可能是会有区别的,所以不推荐使用这种方式来写表达式。不过以学习的目的,还是有必要研究一下的。
这里是在VC6.0和dev-c++下编译运行得出的结果。我们是这样来解释计算结果的:
对于表达式:n=++i + ++i + ++i;
1、首先计算第一个 ++i,这是一个表达式,计算结果为i(为变量而不是数值,即i=i+1,此时i=6);
2、然后计算第二个 ++i,这也是一个表达式,计算结果为i(也是变量,此时i=7);
3、接着计算 第一个和第二个表达式的和,即计算++i + ++i的值,此时相当于计算 i+i的值,即为7+7=14;
4、再接着计算第三个 ++i的值,这也是一个表达式,计算结果仍然为i(同样是变量,此时i=8);
5、再接着计算 14+i 的值(即14+8),返回为22;
6、最后将等号右边表达式的结果赋值给变量n,此时n=22 。
计算结束。

显然,如表达式为 n = ++i + ++i + ++i,则结果输出为31,与我们理解的方式计算结果是相符合的。

以下为参考一老外程序员的解释:

In my case its 22, when i = 5.
It depends upon compiler and even their versions.

I am using gcc 4.1.2

Here, in my case it happens like this.

when you say, n = ++i+ ++i+ ++i;
Compiler treats it as n = a + b + c;
Now it tries to play with two operands(again order can vary,In this example it doesn't matter)

in this case, it has taken a + b;
so it will try to evaluate a and b first, so
a = ++i and b = ++i, 'i' gets incremented twice.

so a + b = i + i = 7 + 7 = 14

At last it will try to evaluate n = 14 + ++i (remember i is 7)

so, n = 14 + 8 = 22.

Here is the assembly code:

0x0804837a <sub+6>:     movl   $0x5,-0x8(%ebp)
0x08048381 <sub+13>:    addl   $0x1,-0x8(%ebp)
0x08048385 <sub+17>:    addl   $0x1,-0x8(%ebp)
0x08048389 <sub+21>:    mov    -0x8(%ebp),%eax
0x0804838c <sub+24>:    add    -0x8(%ebp),%eax
0x0804838f <sub+27>:    addl   $0x1,-0x8(%ebp)
0x08048393 <sub+31>:    add    -0x8(%ebp),%eax
0x08048396 <sub+34>:    mov    %eax,-0x4(%ebp) 
 
As mentioned by other member that he has got 24.
compiler has certainly evaluated all pre increment operator first to output n = 8 + 8 + 8 = 24

 

It depends upon compiler and even their versions.

It also depends on the day of the week the weather the colour of the shirt you are wearing and what you had for breakfast this morning be it is undefined behaviour.

When undefined behaviour is invoked the compiler (and program) can do anything it wants and is not constrained to do the same thing each time it is run including

Giving the result you are expecting
Giving a result close to the result you are expecting
Outputting random text
Exiting with no output or explanation
Raising some sort of exception (SEGV)
Formatting your hard disk
Emailing your electricity supplier and cancelling your contract
Making demons fly out of your nose

The compiler is under NO constraints, undefined behaviour should be avoided at all costs.

int n =++i+ ++i+ ++i;
Is undefined behaviour because the C (and C++) standard states that you may only access a variable once between sequence points if you are accessing it to alter its value (you may of course access it to read any number of times you like if you are not altering its value).

The above line of code only has 1 sequence point, at the ; so it is undefined behaviour surrounding the multiple accesses to i for write.

Other things can cause undefined behaviour, are writing to an invalid memory location or a memory location outside the bounds of an object, main not returning int (in C++) .

Wikipedia has introductory articles to both Undefined behaviour and Sequence Points

 

点赞 (6)

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Captcha Code