C语言上机环境问题?
main(){
int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);
q=(++j)+(++j)+(++j);
printf("%d,%d,%d,%d",p,q,i,j);
}
上面这一段语句用Turbo C环境编译结果是:15 ,24,8,8 无可厚非的。但是用Visual C++6.0环境中C语言编译器编译结果却是:15,22,8,8 这是为什么呢?谭浩强那本C语言程序设计书上给的答案是Turbo C编译的这个答案,实在搞不明白,同样是C语言编译,结果怎么不同呢?另外,我在备考2级C语言,要用的上机环境是Visual C++6.0,如果遇到这样的题,我非晕不可,望诸位编程学者给解释一下,实感激不尽!
追问:您好像理解错了,谭浩强的书上可不是这么讲的。
答案:这个问题是编译器的差异造成的c语言对这个没有硬性规定 所以不同编译器运行过程不同 15,24,8,8的产生就不解释了,解释一下一种可能产生15,22,8,8的编译器的输出
;ebp是基址指针,main当中声明的变量在分配完储存空间以后
;i,j,p,q分别对应到ebp-4,ebp-8,ebp-12,ebp-16(32位环境下int型占4字节)
mov ebp-4,5 ;i=5
mov ebp-8,5 ;j=5
;开始表达式求值
mov edx,[ebp-4] ;p=(i++)+(i++)+(i++)中的第一个i++;把i取出来放到寄存器edx
mov eax,[ebp-4] ;p=(i++)+(i++)+(i++)中的第二个i++;把值取出来放eax
add edx, eax ;p=((i++) + (i++))+(i++) 加法 结果放edx
mov eax,[ebp-4] ;p=(i++)+(i++)+(i++)中的第三个i++;把值取出来放eax
lea eax, [edx+eax] ;edx(刚才加的结果)和eax相加,结果放eax
mov [ebp-12],eax ;结果放回ebp-12,也就是p
;开始把刚才没做的i++做了
lea eax,[ebp-4] ; 取第一个i++的i的地址到eax
inc [eax] ;eax对应的地址即ebp-4自加,即i++
lea eax,[ebp-4] ; 第二个i++,同上
inc [eax] ;
lea eax,[ebp-4] ; 第三个i++,同上
inc [eax] ;
;下面开始第二个表达式求值
lea eax,[ebp-8]
inc [eax]
;和上面类似的这是第一个++j
lea eax,[ebp-8]
inc [eax]
;这是第二个++j
然后这个时候((++j) + (++j))+...已经可以计算了
movl eax,[ebp-8]
movl edx,[ebp-8]
add edx, eax
;和上面一个表达式类似的,计算前半个式子,结果放edx
;然后继续求值的时候遇见(++j)
lea eax,[ebp-8]
inc [eax]
;这是第三个++j
;然后做加法
mov eax, edx ;把刚才的中间结果从edx移到eax
add eax,[ebp-8] ;中间结果与j相加
mov [ebp-16],eax;结果放回ebp-16,也就是q
之后就去调用printf
-----------------------------
总结一下就是说
有的编译器是在整个表达式求解之前就计算所有的++x运算符号,
有的则是按边求解整个表达式,边处理自增运算。
实际上 如果有的编译器在边求值的过程中边处理x++的话 还可能出现p=18的情况。
由于c语言规范没规定这个顺序,因此出现哪个结果都是可能的,
在实际编程中应当尽量避免在 一个表达式 中多次对 同一个运算符 进行自增运算,以免出现歧义。
正确答案应该是 18,21,8,8
main()
{
int i=5,j=5,p,q;
p=(i++)+(i++)+(i++);//第一个i++后变为6第二个i++后变为7所以p=5+6+7=18之后i变为8
q=(++j)+(++j)+(++j);//q=6+7+8=21;之后j=8
printf("%d,%d,%d,%d",p,q,i,j);
}
上一个:编写程序的C语言
下一个:帮忙做一个c语言程序。