读书人

很基础.但是很奇怪的有关问题.

发布时间: 2012-03-08 13:30:13 作者: rapoo

很基础.但是很奇怪的问题....
void main()
{
int arr[]={6,7,8,9,10};

int *ptr=arr;
printf( "%d,%d \n ",*ptr,*(++ptr)); //7, 7
}
输出为什么会是7 , 7
如果把printf( "%d,%d \n ",*ptr,*(++ptr));
改成 printf( "%d \n ",*ptr); //6
printf( "%d \n ",*(++ptr)); //7

难道 printf( "%d,%d \n ",*ptr,*(++ptr)); //7, 7
在这一行里.先执行的是++ptr吗???
同时在帮我看一下.
http://community.csdn.net/Expert/topic/5744/5744579.xml?temp=.1501123
虽然结贴了.但是发现问题1还是没有解决哪..


[解决办法]
在你的 "printf( "%d,%d \n ",*ptr,*(++ptr));//7, 7 "中:

编译器将首先计算该函数参数表中的表达式,由于在上述表达式中,运算符 '++ '有最高的运算优先级,因此编译器将优先对printf函数的形参表中第三个表达式(*++ptr)作前置递增运算:

首先对ptr增量1,再对第3个形参以增量后的ptr作为实参,这样printf函数的第3个参数等同于ptr[1](当然就是指向7)!

由于ptr的新值已自增1(ptr[1]=7),此时编译器继续ptr初始化printf函数的第2个形参,这样第2个参数也等同于ptr[1](当然就是指向7)!


因此输出结果是: 7, 7

C++对函数参数中的表达式求值的顺序并无规定,只是在表达式求值按运算符的优先级依次求值.
[解决办法]
void main()
{
int arr[]={6,7,8,9,10};

int *ptr=arr;
/*printf( "%d,%d,%d \n ",*ptr,*(++ptr),*ptr); */
printf( "%d,%d,%d \n ",*(++ptr),*ptr,*ptr); //7,6,6
}

楼上在看看这个输出
同样,当
void main()
{
int arr[]={6,7,8,9,10};

int *ptr=arr;
*printf( "%d,%d,%d \n ",*ptr,*(++ptr),*ptr);

}

输出确实 7,7,6

呵呵,我也搞不懂了,不过你的理解好四有问题
[解决办法]
的确是调用顺序的问题(从右至左)

看下面的汇编code
printf( "%d,%d \n ",*ptr,*(++ptr));
00401051 mov ecx,dword ptr [ebp-18h]
00401054 add ecx,4 //先++
00401057 mov dword ptr [ebp-18h],ecx
0040105A mov edx,dword ptr [ebp-18h]
0040105D mov eax,dword ptr [edx]
0040105F push eax //此处压入第二个*ptr
00401060 mov ecx,dword ptr [ebp-18h]
00401063 mov edx,dword ptr [ecx]
00401065 push edx //此处压入第一个*ptr
00401066 push offset string "%d,%d,%d \n " (0042001c)
0040106B call printf (004010b0)
00401070 add esp,0Ch


printf( "%d,%d,%d \n ",*ptr,*(++ptr),*ptr);
00401051 mov ecx,dword ptr [ebp-18h]
00401054 mov edx,dword ptr [ecx]
00401056 push edx //此处压入第三个*ptr
00401057 mov eax,dword ptr [ebp-18h]
0040105A add eax,4 //先++
0040105D mov dword ptr [ebp-18h],eax
00401060 mov ecx,dword ptr [ebp-18h]
00401063 mov edx,dword ptr [ecx]
00401065 push edx //此处再压入第二个*ptr
00401066 mov eax,dword ptr [ebp-18h]
00401069 mov ecx,dword ptr [eax]
0040106B push ecx //此处再压入第一个*ptr
0040106C push offset string "%d,%d,%d \n " (0042001c)
00401071 call printf (004010b0)


00401076 add esp,10h

[解决办法]
这谈不上约定,对于不必考虑多路计算优化的编译器来说从后往前计算并压栈的做法比较自然罢了。在栈调用这个约定从后往前的前提下,这样做很自然。

请注意:C++不规定参数(包括表达式子式和函数的参数)的计算次序是有充分理由的。这不是疏忽,而是有意为之,C++标准对表达式子式的求值次序还有专门的论述。
[解决办法]
titicacahang(路过(0731))朋友:

的确试过了,如下:

VC7.1: int pptt = 77;
printf( "%d, %d \n ",pptt, pptt++); // 输出:78, 77

BC6.0: int pptt = 77;
printf( "%d, %d \n ",pptt, pptt++);//输出:78, 77

Gcc: int pptt = 77;
printf( "%d, %d \n ",pptt, pptt++);//输出:78, 77

VC6.0例外: int pptt = 77;
printf( "%d, %d \n ",pptt, pptt++);//:77,77

不过归根结底,该问题就是一个表达式求值顺序问题,先前说过,C++标准对此没有规定,全凭编译器厂商的性趣决定!看来VC7.1比VC6.0更随大流了!

读书人网 >C++

热点推荐