主题:还是关于指针
凌晨一点
[专家分:0] 发布于 2011-04-20 13:49:00
先贴代码:
int zippo[4] = {10, 20, 30, 40};
int * p = zippo;
printf("取值%d 地址%p\n", *p, p); /* 第一条printf */
printf("取值%d 地址%p\n", *p, p++); /* 第二条printf */
我心里认为打印的结果是:
取值10 地址0X22FF60
取值10 地址0X22FF60
因为第二条printf指针p使用的的++是后缀形式,可是真正的打印结果却很诡异
取值10 地址0X22FF60
取值20 地址0X22FF60
间接取值的结果为什么不一样?那从代码和实际打印的结果来看,好像顺序反了。。。
为了弄明白事情真相,我又改了代码:
int zippo[4] = {10, 20, 30, 40};
int * p = zippo;
printf("取值%d 地址%p\n", *p, p); /* 第一条printf */
printf("地址%p 取值%d\n", p++, *p); /* 第二条printf */
我心里认为结果是:
取值10 地址0X22FF60
地址0X22FF60 取值20
实际结果却是:
取值10 地址0X22FF60
地址0X22FF60 取值10
我觉得事情越来越诡异,顺序好像是反过来的……第二条printf的取值应该是zippo的第二个元素20啊,怎么会是10呢,纳闷。
我又改了代码,把两条printf语句整合成一条:
int zippo[4] = {10, 20, 30, 40};
int * p = zippo;
printf("取值%d 地址%p 地址%p 取值%d\n", *p, p, p++, *p);
我认为结果是:取值10 地址0X22FF60 地址0X22FF60 取值20
可是实际打印结果是:取值20 地址0X22FF64 地址0X22FF60 取值10
天啊,这都怎么回事啊?是编译器的问题还是自己的问题啊,那个地址是编译器给的,抄出来希望能更好讲述我的问题。我真是二丈和尚摸不着头脑啊,想了几天还是找不出个能解释这种现象的理由,实在是太郁闷了。
求讲解、求指点。最好能详细一些,我不知道因为怎样百度能找到我想要的答案……所以,求助没有办法的办法,我也知道自己想出来能自己最有帮助,可我实在是想不出,为何结果是这样的。哪里有说得不对请指出,我使用的编译器是Dev-c++
回复列表 (共16个回复)
沙发
leftcopychenhx [专家分:20] 发布于 2011-04-20 15:14:00
你代码的操作属"未定义"行为,ANSI C没有具体的标准,各种编译器会给出不同的解释;gcc可能会是从代码的右端开始进行的。
c primer plus 中建议不要使用这样的操作。
板凳
凌晨一点 [专家分:0] 发布于 2011-04-20 16:40:00
未定义?怎么说?
3 楼
linjiuwu [专家分:30] 发布于 2011-04-20 17:52:00
在您的编译器中,printf打印是从右端开始的。从右边到左来计算便可理解了。
4 楼
cgl_lgs [专家分:21040] 发布于 2011-04-21 12:01:00
不要在函数调用时又用X++又用X,这样就是未定义的。。。
5 楼
凌晨一点 [专家分:0] 发布于 2011-04-22 12:22:00
难道指针不能这样用吗?书中并没有说到呀,我不能理解
6 楼
cgl_lgs [专家分:21040] 发布于 2011-04-22 14:46:00
教科书没说的东西海了去了。
注释
缩进
风格
版本管理
……
我们跟你说绝对不是在害你,而是在帮你。
7 楼
彬雪飞舞 [专家分:40] 发布于 2011-04-24 10:31:00
[quote]在您的编译器中,printf打印是从右端开始的。从右边到左来计算便可理解了。在函数中都这样的
[/quote]
8 楼
凌晨一点 [专家分:0] 发布于 2011-04-25 13:18:00
我不是那个意思,我是说,书里没有说而已
9 楼
cgl_lgs [专家分:21040] 发布于 2011-04-25 17:25:00
嗯,我们也没有别的意思,只是一本书确实难以容下太多的东西,而BBS正好弥补了这个不足:)
10 楼
windy0will [专家分:2300] 发布于 2011-04-25 21:47:00
确实,一两本书不可能容纳很多东西。有的东西要多参考别人的意见,然后自己在多思考,并且也不见得自己能够思考得全面。在BBS中把问题贴出来,和大家讨论, 结合几个人的思路也许就豁然开朗了。
那时侯刚来论坛的时候,很多大牛热心的帮我解决问题,感觉那段时间进步的很快。
比如说为什么printf("取值%d 地址%p\n", *p, p++); 这样的语句是未定义的呢?我是这样理解的:
一般而言,编译器会这样来处理这个语句:
1. 把最右边的p如栈
2. p自增
3. 把*p入栈
4. 把字符串"取值%d 地址%p\n"入栈
5. 调用函数printf
这样,很显然1,2和3是有数据相关的,在执行3以前2必须完成,2以前1必须完成。
还有一种是这样
1. 把最右边的p如栈
3. 把*p入栈
4. 把字符串"取值%d 地址%p\n"入栈
2. p自增 //也可能放的5后面
5. 调用函数printf
这样1和3,4这三个语句基本上可以同时执行,很显然这样的效率要比上面的好一些。
但是前面那种情况让人更容易理解。 c标准并没有把它规定死,把它留给实现者来决定。
未定义的行为并不是错误,可以这样用(但最好不要这样用,除非您完全不要考虑移植)。
我来回复