visual C++6.0中编写C程序
输入以下程序main(){inti=8;printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);}为何得...
输入以下程序
main()
{
int i=8;
printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);
}
为何得到的输出是 8 7 8 8 -8 -8
是以什么顺序来输出的呢? 展开
main()
{
int i=8;
printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);
}
为何得到的输出是 8 7 8 8 -8 -8
是以什么顺序来输出的呢? 展开
5个回答
展开全部
从右到左,由于右边4个都是后加/减运算(先运算再加/减),所有后4个输出全是8(或-8),右边数第五个就是:--i,是先减再运算,输出为7,再左边就是:++i,是先加再运算,输出为8.
你可能会问那后加/减怎么没算,那些是在执行完整个printf之后才会计算的,你可以改一下:
printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i--,i--,-i--,-i--);
printf("i=%d\n",i);
第二句是增加的,由于你那里是3个加加,3个减减,结果还是8,按照我写的,前面的打印结果不变,多打印一行:
i=4
我想这下就明白了,4个后减减在执行完printf之后才参与运算。
你可能会问那后加/减怎么没算,那些是在执行完整个printf之后才会计算的,你可以改一下:
printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i--,i--,-i--,-i--);
printf("i=%d\n",i);
第二句是增加的,由于你那里是3个加加,3个减减,结果还是8,按照我写的,前面的打印结果不变,多打印一行:
i=4
我想这下就明白了,4个后减减在执行完printf之后才参与运算。
展开全部
我曾经回答过这个问题
printf对不同的调用约定结果是不一样的!故此题没有标准答案(楼下给出的各种答案都是正确的),若出题人未给出具体的编译器而出此题,那该命题人的C水平可想而知!下面的解释将会有点深奥,楼主懂的话看 不懂就算了!
在VC++6中对于 printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);这个表达式,先计算的是-i--,然后是-i++,接下来依次是i--,i++,--i,++i。-i--计算结果是-8,计算结束i仍旧是8.-i++结果也是-8; 计算结束 i还是8;接下来计算i--计算结果是8 计算结束 i还是8;i++计算结果是8 计算结束i还是8;--i计算结果为7计算结束i是7;接下来计算++i由于此时i为7所以计算结果为8计算结束i=8;printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);语句执行完毕i=8;
0040D928 |. C745 FC 08000>mov[local.i],8 把8传送到[local.i]
0040D92F |. 8B45 FC mov eax,[local.i] 把8传给eax寄存器
0040D932 |. F7D8 neg eax 对8 取补(你可以简单理解为求反)
0040D934 |. 8945 F8 mov [local.2],eax -8传给[local.2](你可以简单理解为[local.2]是变量)
0040D937 |. 8B4D F8 mov ecx,[local.2] -8 传给ecx
0040D93A |. 51 push ecx ;/<%d>ecx入栈(-i--)
0040D93B |. 8B55 FC mov edx,[local.i] ; |8传给edx
0040D93E |. F7DA neg edx ; |edx求反得-8
0040D940 |. 8955 F4 mov [local.3],edx ; |-8 给[local.3]
0040D943 |. 8B45 F4 mov eax,[local.3] ; |[local.3]传给eax
0040D946 |. 50 push eax ;|<%d>eax入栈此时eax=-8(-i++)
0040D947 |. 8B4D FC mov ecx,[local.i] ; |ecx=8
0040D94A |. 894D F0 mov [local.4],ecx ; |[local.4]=8
0040D94D |. 8B55 F0 mov edx,[local.4] ; |edx=8
0040D950 |. 52 push edx ;|<%d>edx入栈(i--)
0040D951 |. 8B45 FC mov eax,[local.i] ; |
0040D954 |. 8945 EC mov [local.5],eax ; |
0040D957 |. 8B4D EC mov ecx,[local.5] ; |
0040D95A |. 51 push ecx ;|<%d>ecx入栈(i++)
0040D95B |. 8B55 FC mov edx,[local.i] ; |
0040D95E |. 83EA 01 sub edx,1 ; |先自减运算--i运算后edx=7
0040D961 |. 8955 FC mov [local.i],edx ; |
0040D964 |. 8B45 FC mov eax,[local.i] ; |
0040D967 |. 50 push eax ;|<%d>eax(7)入栈(--i)
0040D968 |. 8B4D FC mov ecx,[local.i] ; |
0040D96B |. 83C1 01 add ecx,1 ; |先自增运算运算后ecx=8
0040D96E |. 894D FC mov [local.i],ecx ; |
0040D971 |. 8B55 FC mov edx,[local.i] ; |
0040D974 |. 52 push edx ; |<%d>edx(8)入栈(++i)
0040D975 |. 68 1C204200 push 4.0042201C ; |format = "%d
%d
%d
%d
%d
%d
"
0040D97A |. 8B45 FC mov eax,[local.i] ; |
0040D97D |. 83C0 01 add eax,1 ; |对i++的后自增运算处理
0040D980 |. 8945 FC mov [local.i],eax ; |
0040D983 |. 8B4D FC mov ecx,[local.i] ; |
0040D986 |. 83E9 01 sub ecx,1 ; | 对i++的后自减运算处理
0040D989 |. 894D FC mov [local.i],ecx ; |
0040D98C |. 8B55 FC mov edx,[local.i] ; |
0040D98F |. 83C2 01 add edx,1 ; |对-i++的后自增运算处理
0040D992 |. 8955 FC mov [local.i],edx ; |
0040D995 |. 8B45 FC mov eax,[local.i] ; |
0040D998 |. 83E8 01 sub eax,1 ; |对-i--的后自减运算处理
0040D99B |. 8945 FC mov [local.i],eax ; |
0040D99E |. E8 DD38FFFF call 4.printf ; \printf
从以上汇编代码中不难看出参数是从右到左传进去的了吧?
每次传递一个参数都要做自增自减这些处理!所以自然会出现那种情况!
对于函数的调用约定常用的有这么几种(仅仅考虑参数入栈顺序,不考虑栈平衡)
从右到左依次入栈:__stdcall,__cdecl,__thiscall
从左到右依次入栈:__pascal,__fastcall
但是VC6.0只可以使用__stdcall,__cdecl,__fastcall这三种
VC6在stdio.h中定义printf为:_CRTIMP int __cdecl printf(const char *, ...);
属于从右到左入栈,故计算顺序也是从右到左
gcc默认好像优先采用fastcall,所以结果不一样 可想而知,但我记得有gcc 有参数可以制定的
__stdcall 是标准调用约定也是WINAPI调用约定。
__cdecl是C语言调用约定。
__fastcall虽然从左到右依次入栈但是是有前提的
__fastcall函数调用约定为了使函数调用更快不再将参数放在栈中,VC编译器采用调用约定传递参数时,最左边的两个不大于4个字节(DWORD)的参数分别放在ecx和edx寄存器。当寄存器用完的时候,其余参数仍然从右到左的顺序压入堆栈
故我不能给你演示从左到右传参的例子,因为我手上没有支持pascal调用约定的编译器!
如果printf()采用pascal调用约定那么结果就是你想的那种了!
够详细了吧,也许已经详细得你有点看不懂了,没关系我给你注释了!纯手打!如有雷同纯属巧合!
printf对不同的调用约定结果是不一样的!故此题没有标准答案(楼下给出的各种答案都是正确的),若出题人未给出具体的编译器而出此题,那该命题人的C水平可想而知!下面的解释将会有点深奥,楼主懂的话看 不懂就算了!
在VC++6中对于 printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);这个表达式,先计算的是-i--,然后是-i++,接下来依次是i--,i++,--i,++i。-i--计算结果是-8,计算结束i仍旧是8.-i++结果也是-8; 计算结束 i还是8;接下来计算i--计算结果是8 计算结束 i还是8;i++计算结果是8 计算结束i还是8;--i计算结果为7计算结束i是7;接下来计算++i由于此时i为7所以计算结果为8计算结束i=8;printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i++,i--,-i++,-i--);语句执行完毕i=8;
0040D928 |. C745 FC 08000>mov[local.i],8 把8传送到[local.i]
0040D92F |. 8B45 FC mov eax,[local.i] 把8传给eax寄存器
0040D932 |. F7D8 neg eax 对8 取补(你可以简单理解为求反)
0040D934 |. 8945 F8 mov [local.2],eax -8传给[local.2](你可以简单理解为[local.2]是变量)
0040D937 |. 8B4D F8 mov ecx,[local.2] -8 传给ecx
0040D93A |. 51 push ecx ;/<%d>ecx入栈(-i--)
0040D93B |. 8B55 FC mov edx,[local.i] ; |8传给edx
0040D93E |. F7DA neg edx ; |edx求反得-8
0040D940 |. 8955 F4 mov [local.3],edx ; |-8 给[local.3]
0040D943 |. 8B45 F4 mov eax,[local.3] ; |[local.3]传给eax
0040D946 |. 50 push eax ;|<%d>eax入栈此时eax=-8(-i++)
0040D947 |. 8B4D FC mov ecx,[local.i] ; |ecx=8
0040D94A |. 894D F0 mov [local.4],ecx ; |[local.4]=8
0040D94D |. 8B55 F0 mov edx,[local.4] ; |edx=8
0040D950 |. 52 push edx ;|<%d>edx入栈(i--)
0040D951 |. 8B45 FC mov eax,[local.i] ; |
0040D954 |. 8945 EC mov [local.5],eax ; |
0040D957 |. 8B4D EC mov ecx,[local.5] ; |
0040D95A |. 51 push ecx ;|<%d>ecx入栈(i++)
0040D95B |. 8B55 FC mov edx,[local.i] ; |
0040D95E |. 83EA 01 sub edx,1 ; |先自减运算--i运算后edx=7
0040D961 |. 8955 FC mov [local.i],edx ; |
0040D964 |. 8B45 FC mov eax,[local.i] ; |
0040D967 |. 50 push eax ;|<%d>eax(7)入栈(--i)
0040D968 |. 8B4D FC mov ecx,[local.i] ; |
0040D96B |. 83C1 01 add ecx,1 ; |先自增运算运算后ecx=8
0040D96E |. 894D FC mov [local.i],ecx ; |
0040D971 |. 8B55 FC mov edx,[local.i] ; |
0040D974 |. 52 push edx ; |<%d>edx(8)入栈(++i)
0040D975 |. 68 1C204200 push 4.0042201C ; |format = "%d
%d
%d
%d
%d
%d
"
0040D97A |. 8B45 FC mov eax,[local.i] ; |
0040D97D |. 83C0 01 add eax,1 ; |对i++的后自增运算处理
0040D980 |. 8945 FC mov [local.i],eax ; |
0040D983 |. 8B4D FC mov ecx,[local.i] ; |
0040D986 |. 83E9 01 sub ecx,1 ; | 对i++的后自减运算处理
0040D989 |. 894D FC mov [local.i],ecx ; |
0040D98C |. 8B55 FC mov edx,[local.i] ; |
0040D98F |. 83C2 01 add edx,1 ; |对-i++的后自增运算处理
0040D992 |. 8955 FC mov [local.i],edx ; |
0040D995 |. 8B45 FC mov eax,[local.i] ; |
0040D998 |. 83E8 01 sub eax,1 ; |对-i--的后自减运算处理
0040D99B |. 8945 FC mov [local.i],eax ; |
0040D99E |. E8 DD38FFFF call 4.printf ; \printf
从以上汇编代码中不难看出参数是从右到左传进去的了吧?
每次传递一个参数都要做自增自减这些处理!所以自然会出现那种情况!
对于函数的调用约定常用的有这么几种(仅仅考虑参数入栈顺序,不考虑栈平衡)
从右到左依次入栈:__stdcall,__cdecl,__thiscall
从左到右依次入栈:__pascal,__fastcall
但是VC6.0只可以使用__stdcall,__cdecl,__fastcall这三种
VC6在stdio.h中定义printf为:_CRTIMP int __cdecl printf(const char *, ...);
属于从右到左入栈,故计算顺序也是从右到左
gcc默认好像优先采用fastcall,所以结果不一样 可想而知,但我记得有gcc 有参数可以制定的
__stdcall 是标准调用约定也是WINAPI调用约定。
__cdecl是C语言调用约定。
__fastcall虽然从左到右依次入栈但是是有前提的
__fastcall函数调用约定为了使函数调用更快不再将参数放在栈中,VC编译器采用调用约定传递参数时,最左边的两个不大于4个字节(DWORD)的参数分别放在ecx和edx寄存器。当寄存器用完的时候,其余参数仍然从右到左的顺序压入堆栈
故我不能给你演示从左到右传参的例子,因为我手上没有支持pascal调用约定的编译器!
如果printf()采用pascal调用约定那么结果就是你想的那种了!
够详细了吧,也许已经详细得你有点看不懂了,没关系我给你注释了!纯手打!如有雷同纯属巧合!
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
哈哈,我的GCC和visual c++ 2010运行显示的是
8
8
7
8
-7
-8
但是我理论上推断是
8
7
7
8
-7
-8
其实这个问题涉及编译器压栈和运算符优先级调配,理论上是从右往左计算后压入函数栈,然后不断弹出栈顶元素输出到屏幕。具体原理我再查查看。
8
8
7
8
-7
-8
但是我理论上推断是
8
7
7
8
-7
-8
其实这个问题涉及编译器压栈和运算符优先级调配,理论上是从右往左计算后压入函数栈,然后不断弹出栈顶元素输出到屏幕。具体原理我再查查看。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
8,8,7,8,-9,-8 这是我在linux上用gcc编译出来的结果
不过printf输出是从左至右,计算则是从右至左
不过printf输出是从左至右,计算则是从右至左
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
从左到右啊
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询