2014-09-30 74 views
-6
#include<stdio.h> 
int main() 
{ 
int a=1; 
printf("%d%d%d",a,++a,a++); 

} 

这里为什么是输出331和122不输出错误在C程序

我互联网上找到的理由是,arguements传递格罗姆从右到左。首先a ++然后++ a然后a得到评估,然后以相反的顺序打印。这是正确的原因吗?

+0

没有告诉我原因 – 2014-09-30 10:07:50

+0

原因-undefined行为 – 2014-09-30 10:09:14

+0

@酷guybut我的书说,它有什么与调用约定 – 2014-09-30 10:10:43

回答

-1

GCC -S your_source.c解释你的问题

movl $1, -4(%rbp) #, a 
    movl -4(%rbp), %ecx # a, a.0 
    addl $1, -4(%rbp) #, a 
    addl $1, -4(%rbp) #, a 
    movl -4(%rbp), %edx # a, tmp61 
    movl -4(%rbp), %eax # a, tmp62 
    movl %eax, %esi  # tmp62, 
    movl $.LC0, %edi  #, offset to "%d%d%d" sttring 
    movl $0, %eax  #, 
    call printf # 

编译器开发者绝对不要指望有人会尝试使用它在这样一个丑陋的方式

如果你真的需要122:然后更改ASM代码如下:

movl $1, -4(%rbp) #, a 
    movl -4(%rbp), %eax # a, a.0 
    addl $1, -4(%rbp) #, a 
    movl -4(%rbp), %edx # a, tmp61 
    movl -4(%rbp), %ecx # a, tmp62 
    movl %eax, %esi  # tmp62, 
    movl $.LC0, %edi  #, 
    movl $0, %eax  #, 
    call printf # 
    addl $1, -4(%rbp) #, a 
    leave 
-3

输出取决于机器体系结构和编译器。 请参阅:Compilers and argument order of evaluation in C++

在这种情况下,考虑到其中编译器符合执行顺序为从右到左的机器:由左即

第三输出,一个++将为1,因为它是一个后递增的,这意味着a的现有值用于printf,然后其内存地址处的值递增并保存。因此,printf获取1作为参数,之后a变为2.

从左侧开始的第二个输出即++ a将是a(从上面2)加1的值。请注意,因为它是预增量。首先更新a地址处的值,然后将此更新值传递给printf。因此,2 + 1 = 3

左起第一个输出的值,也就是现在的3

+0

r使用让我们c – 2014-09-30 10:17:02

+0

@IshanBansal它不依赖于书友。它取决于参数类型,被调用函数的调用约定,构造和编译器。在x86上,Pascal调用约定从左到右评估参数,而在C调用约定(__cdecl)中,它是正确的。在这里阅读更多http://stackoverflow.com/questions/621542/compilers-and-argument-order-of-evaluation-in-c – kundan 2014-09-30 10:34:28

+0

我不赞美你。你的回答是不正确的。 – 2014-09-30 11:13:40