2012-06-08 199 views
2

可能重复的:
Undefined Behavior and Sequence Points评估宏

我有理解下面的宏麻烦:

#define CUBE(x) ((x)*(x)*(x)) 

我的代码:

int y=5; 
print("Cube = %d",CUBE(++y)); 

这段代码打印512(使用Microsoft Visual Studio)

我在期待打印:((++5)*(++6)*(++7)) = (6*7*8) = 336
这是如何评估?

同样的代码是用Dev C++编译器编译的,结果是392!

有人可以解释为什么两个编译器显示完全相同的代码不同的结果?

++y这个怎么评估的?

+0

未定义行为...不要那样做。 – jn1kk

回答

1

CUBE(++ y));变成(++ y * ++ y * ++ y) - 以什么顺序评估?

要技术 - 它是不确定的,改变功能点之间相同的变量

编辑:见Undefined behavior and sequence points

的Visual C++似乎来评价这是y+=3; y*y*y; so 8*8*8 = 512
382为7 * 7 * 8,以便开发的C++大概估计第一部分为y+=2; y*y;然后49*y++

1

在你的表达式中没有sequence points,所以当副作用(即增量结果ing y)变得可见的是未定义的。简而言之,在表达式评估完成之前,编译器可随时将++y的结果存储回y

这是制作带有副作用表达式的宏的危险。用同样的功能你会更好。

3

当宏被展开时,y的值被修改不止一次而没有中间顺序点。
这是未定义的行为

未定义行为意味着任何行为都是可能的,您的程序不是有效的c程序。
因此,您会在不同的编译器上看到不同的输出。

0

预编译器评估该宏

#define CUBE(x) ((x)*(x)*(x)) 
在你的代码

int y=5; 
print("Cube = %d",CUBE(++y)); 

int y=5; 
print("Cube = %d",((++y)*(++y)*(++y))); 

写这样的代码混乱,结果是不确定的。

不同的编译器行为可能不同。

避免使用这种结构,你不会面临这样的问题。

+0

它明确未定义 –

0

我们需要查看代码(gcc -S.c)的ASM(汇编)以了解它究竟发生了什么。

在开发的C++编译器ASM看起来像

1)  movl $5, 28(%esp) 
2)  addl $1, 28(%esp) 
3)  addl $1, 28(%esp) 
4)  movl 28(%esp), %eax 
5)  imull 28(%esp), %eax 
6)  addl $1, 28(%esp) 
7)  imull 28(%esp), %eax 

它显示值5被移动到%尤指(1)中,然后加入两个时间有(2 & 3),所以现在y的值变为7;这个值现在被移到eax寄存器(4)并且乘以7 * 7(5);现在给y(6)加1,然后乘以eax;所以答案为7 * 7 * 8 = 392

在Microsoft Visual Studio这将是8 * 8 * 8