解释为什么j想出150?

时间:2014-02-15 15:49:04

标签: c

#include <stdio.h>

main() {
  int i=3,j;  
  j=++i*++i*++i;
  printf("%d,%d",i,j);
}

答案即将到来,i = 6,j = 150 请解释为什么j出现150 ??

3 个答案:

答案 0 :(得分:9)

此未定义行为是由于序列点。请参阅这些链接

Undefined behavior and sequence points

http://c-faq.com/expr/seqpoints.html

答案 1 :(得分:2)

编译器中的j=++i*++i*++i将分解为1:(++i*++i)*++i,然后它将计算左操作数,然后计算右操作数。左边的是一个括号,所以它会看到里面的东西。 ++i*++i将被评估为(++i)*(++i),然后编译器将计算左右操作数,然后它将进行乘法运算。左操作数会将i增加1并返回i,右操作数会将i增加1并返回i。因此,我们在i*i表达式的第一个括号中得到1i5,因此它将返回25。现在我们得到(25)*(++i),编译器检查两个操作数,左边一个返回25,右边一个增加i一个并返回ii现在是{{ 1}}所以我们得到了6。这就是gcc的工作原理

答案 2 :(得分:1)

结果实际上取决于编译器。

我用gcc和clang编译了它。 Gcc输出150,而clang输出120。

但是反汇编可以说明为什么j = 150:

movl   $0x3,-0xc(%rbp)  // i = 3
movl   $0x0,-0x10(%rbp) // j = 0
mov    -0xc(%rbp),%eax  // %eax = i = 3
add    $0x1,%eax        // %eax += 1, %eax = 4 
mov    %eax,-0xc(%rbp)  // move %eax back to i, ie i = 4
mov    -0xc(%rbp),%eax  // %eax = i = 4
add    $0x1,%eax        // %eax = 5
mov    %eax,-0xc(%rbp)  // move %eax back to i, ie i = 5
mov    -0xc(%rbp),%eax  // store i in %eax
mov    -0xc(%rbp),%ecx  // store i in %ecx
imul   %ecx,%eax        // %eax * %ecx, %eax = 5*5 = 25
mov    -0xc(%rbp),%ecx  // store i in %ecx
add    $0x1,%ecx        // %ecx + 1, %ecx = 6
mov    %ecx,-0xc(%rbp)  // move %ecx back to i, ie i = 6 
mov    -0xc(%rbp),%ecx  // store i in %ecx
imul   %ecx,%eax        // %eax * %ecx, %eax = 6*25=150
mov    %eax,-0x10(%rbp) // move %eax to j, ie j = 150