2011-03-14 74 views
1

请解释在每种情况下工作。解释这个C程序的工作

为什么这两种情况具有相同的输出?

案例一:

int main (void) 
{ 
    int i = 5; 
    if(i == ++i)   //plz explain here How values are checked 
     printf("Equal"); 
    else 
     printf("Not Equal"); 

    return 0; 
} 
//Output: Equal; 

案例二:

int main (void) 
{ 
    int i = 5; 
    if(++i == i)   //plz explain here How values are checked 
     printf("Equal"); 
    else 
     printf("Not Equal"); 

    return 0; 
} 
//Output: Equal; 

回答

10

无论这些方案是有效的;您不允许读取和更新相同的变量,而没有中间的序列点。因此,这些程序都是未定义的行为,因此它们可能碰巧在你的编译器和机器上返回相同的答案并不意味着什么。

+0

但是这两个程序都正确执行 – 2011-03-14 04:20:01

+7

@Javed Akram:是的 - 未定义行为的一个可能结果是代码似乎正常工作,甚至可能产生您期望的结果。再次,它可能不会做任何一个。当然,最常见的结果是,它似乎在测试中运行良好,然后在为客户端演示时做了一些可怕的事情。 – 2011-03-14 04:22:57

+0

@Jerry好吧,我不认为机器代码会因演示而波动,但请尝试切换编译器(即使是简单的升级也可以做到这一点),看看你什么时候开始哭泣。 – stefan 2011-03-14 04:24:43

0

它是相等的,因为这是C.另一个回答说,这个操作的结果是不确定的,因为你违反了C规则 - 这意味着在切换编译器时你不能保证相同的答案(尽管所有的编译器可能是实施类似,这并不能保证)。 C允许你在脚下拍摄自己的事实并不意味着这样做是一种好的做法。

现在,它为什么会起作用?

猜想#1:

i可以被存储在寄存器中,说r1,并且编译器可被编译此整个比较成一个单一的CMP指令,具有自动增量的寻址模式。假设它是CMP ++r1, r1CMP r1, ++r1,然后根据实际的CPU,两者可能会返回一个真正的比较结果。

猜想#2:

编译器可编译比较为:

inc r1 // increment r1 
CMP r1, r1 // compare with itself 

猜想三:

编译器可优化,始终把一个简单的变量访问右侧。它可以这样做,因为==运算符中的执行顺序是未定义的,编译器可以按照它的喜好重新排列。