读书人

*(ptr++) += 123 的懂得

发布时间: 2013-01-02 13:08:45 作者: rapoo

*(ptr++) += 123 的理解
这样的话:

【代码1:】


#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>

int main()
{
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++) = *(ptr++) + 123;
printf("%d ,%d\n",*ptr,*(++ptr));

system("pause");
return 0;
}

结果是:9 ,9



但是这个:

【代码2:】

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>

int main()
{
int arr[] = {6,7,8,9,10};
int *ptr = arr;
*(ptr++) += 123;
printf("%d ,%d\n",*ptr,*(++ptr));

system("pause");
return 0;
}


这样的话运行结果是8 ,8



我有几点疑问:
1、*(ptr++) += 123; 的写法与*(ptr++) = *(ptr++) + 123; 的写法难道是有区别的吗?他们应该在任何时候都是对等的吧?

2、按照我的理解:
【代码1:】的结果应该是8,9
【代码2:】的结果应该是7,8

3、printf("%d ,%d\n",*ptr,*(++ptr));
这一句的话,难道还是先执行*(++ptr),然后再执行*ptr吗?这个到底是c89,c99标准规定的还是是未定义行为,跟具体的编译器,集成环境有关系吗,它到底是怎么自行的呢,是参数*(++ptr)先入栈,然后参数*ptr才入栈吗?这个是标准规定的吗?


[解决办法]
3、printf("%d ,%d\n",*ptr,*(++ptr));
这一句的话,难道还是先执行*(++ptr),然后再执行*ptr吗?这个到底是c89,c99标准规定的还是是未定义行为,跟具体的编译器,集成环境有关系吗,它到底是怎么自行的呢,是参数*(++ptr)先入栈,然后参数*ptr才入栈吗?这个是标准规定的吗?

>> 应该是先执行*(++ptr), printf是输入参数数目不定, 对参数的解析是从后往前,即从右往左
[解决办法]
不太懂汇编,不过从看反汇编过来,printf("%d ,%d\n",*ptr,*(++ptr));应该是先执行的(++ptr),而*(ptr++) = *(ptr++) + 123; ptr指针加了2次。

//第一段代码
*(ptr++) = *(ptr++) + 123;
004113E7 mov eax,dword ptr [ptr]
004113EA mov ecx,dword ptr [eax]
004113EC add ecx,7Bh
004113EF mov edx,dword ptr [ptr]
004113F2 mov dword ptr [edx],ecx
004113F4 mov eax,dword ptr [ptr]
004113F7 add eax,4
004113FA mov dword ptr [ptr],eax
004113FD mov ecx,dword ptr [ptr]
00411400 add ecx,4
00411403 mov dword ptr [ptr],ecx
printf("%d ,%d\n",*ptr,*(++ptr));
00411406 mov eax,dword ptr [ptr]
00411409 add eax,4


0041140C mov dword ptr [ptr],eax
0041140F mov esi,esp
00411411 mov ecx,dword ptr [ptr]
00411414 mov edx,dword ptr [ecx]
00411416 push edx
00411417 mov eax,dword ptr [ptr]
0041141A mov ecx,dword ptr [eax]
0041141C push ecx
0041141D push offset string "%d ,%d\n" (415644h)
00411422 call dword ptr [__imp__printf (4182BCh)]
00411428 add esp,0Ch
0041142B cmp esi,esp
0041142D call @ILT+305(__RTC_CheckEsp) (411136h)


而*(ptr++) += 123;,ptr指针只加了一次,同样printf("%d ,%d\n",*ptr,*(++ptr));,先执行的应该是++ptr.

*(ptr++) += 123;
004113E7 mov eax,dword ptr [ptr]
004113EA mov ecx,dword ptr [eax]
004113EC add ecx,7Bh
004113EF mov edx,dword ptr [ptr]
004113F2 mov dword ptr [edx],ecx
004113F4 mov eax,dword ptr [ptr]
004113F7 add eax,4
004113FA mov dword ptr [ptr],eax
printf("%d ,%d\n",*ptr,*(++ptr));
004113FD mov eax,dword ptr [ptr]
00411400 add eax,4
00411403 mov dword ptr [ptr],eax
00411406 mov esi,esp
00411408 mov ecx,dword ptr [ptr]
0041140B mov edx,dword ptr [ecx]
0041140D push edx
0041140E mov eax,dword ptr [ptr]
00411411 mov ecx,dword ptr [eax]
00411413 push ecx
00411414 push offset string "%d ,%d\n" (415644h)
00411419 call dword ptr [__imp__printf (4182BCh)]
0041141F add esp,0Ch
00411422 cmp esi,esp


00411424 call @ILT+305(__RTC_CheckEsp) (411136h)


[解决办法]
*(ptr++) += 123;
*(ptr++) = *(ptr++) + 123;
一个是一个++,另一个是两个++,怎么可能一样呢?
[解决办法]
3、printf("%d ,%d\n",*ptr,*(++ptr));
VC,VS中函数默认的入栈顺序从右向左,因此先执行*(++ptr)再输出。

如下面这个程序会输出5 ,5
#include <stdio.h>
int main()
{
int i = 4;
printf("%d ,%d\n", i, ++i);
return 0;
}

[解决办法]
1. *(ptr++) = *(ptr++) + 123;
实际执行时,右边的ptr++会先被执行一次,然后把结果赋给左边,ptr++又被执行一次,所以ptr一共被加了两次
很显然,第二段代码里ptr只被加了一次

2. 关于printf
由于函数间参数传递是通过栈,并且入参是前面的参数在堆栈的低位,所以对于printf("%d ,%d\n",*ptr,*(++ptr));必须先把*(++ptr)的值压栈,然后再压*ptr,最后压"%d ,%d\n",因此ptr会被先加一次
[解决办法]

[解决办法]
引用:
为什么要为了这些毫无意义的东西纠结????????????????????????



回忆下 鲁迅如何解释自己的鼻子扁平
[解决办法]
printf函数执行顺序自右向左
输出顺序自左向右
[解决办法]
lz说对了
  *(ptr++) += 123;   
printf("%d ,%d\n",*ptr,*(++ptr));

着两行都是未定义行为

读书人网 >C语言

热点推荐