C/C++中指针加 1 的问题

  先用贝尔的一道笔试题简要的说明一下吧: 【题】说明以下程序。 #include int main(void) { unsigned int a[3] = {0x01020304, 0x05060708, 0x090a0b0c}; unsigned int *p = (unsigned int *)((int)a +1);① printf("%x/n", *p); return 0; } 【题目解析】 这段程序的输出结果应该是 8010203(即0x08010203)。 内存存储结构如(图1)所示(在 big-endian 的系统中)。在①处的语句中,首先把数组 a 的首地址转化为整型,然后再加 1 ,再强制转化为 (unsigned int *) ,这个时候 p 值应该是 0x1235,所以取的是从 0x1235 到 0x1238 四个字节组成的新的整数,所以就是 0x08010203。 给出公式的话就是 (a[0]>>8 | a[1]<<24)。 图 1 内存结构示意图 【补充说明】 看一下这条语句输出是什么呢? p = a; printf("%d %08x %d %d %d", (p+1)-p, *(p+1), &a[1]-&a[0],(int)(p+1)-(int)p, (char *)(p+1)-(char *)p ); 结果是: 1 05060708 1 4 4 第一个输出大家可能理解为理所当然了,我们先看后面的结果。 第二个输出值是数组 a 的 a[1] 元素的值,也就是说 (p+1) 指向的地址是 0x1238,而不是0x1235。为什么呢?因为指针加 1 的时候,实际上是加上了他所指向数据类型的宽度,这样指针就可以指向下一个元素而不是一个元素的一半了。汇编代码如下: 0040106A mov ecx,dword ptr [ebp-10h] 0040106D add ecx,4 ;注意这里,实际加的是 4,而不是1 00401070 sub ecx,dword ptr [ebp-10h] 00401073 sar ecx,2 00401076 push ecx 第三个输出按理来说应该是 0x1238-0x1234 = 4,但是为什么是 1 呢?因为返回的是这种元素的个数,而不是真正的地址差值,也就是把差值再除以元素宽度。下面是 VC 的汇编代码,参数 &a[1]-&a[0] 的压栈过程。 00401043 lea ecx,[ebp-8] ; 取 a[1] 的地址值 00401046 lea edx,[ebp-0Ch] ; 取 a[0] 的地址值 00401049 sub ecx,edx ; 计算地址值之差,并放入 ecx 中 (值为4) 0040104B sar ecx,2 ; 将 ecx 中的数值右移两位,也就是除以 4 (值为1) 0040104E push ecx ; 参数压栈,供函数 printf() 使用 第四个输出是 4,因为int类型的相减就是实际数字的相减,不需考虑其它因素,汇编代码如下: 00401063 mov edx,dword ptr [ebp-10h] 00401066 mov eax,dword ptr [edx+4] 00401069 push eax ; 注意!压栈之前没有右移操作 第五个输出,讲到这里 我想大家应该都明白了为什么是4了,我只给出汇编代码: 0040104F mov eax,dword ptr [ebp-10h] 00401052 add eax,4 00401055 sub eax,dword ptr [ebp-10h] 00401058 push eax 现在在回头看一下第一个输出结果的汇编代码。在执行 p+1 的时候实际上是加了 4 (int类型的宽度),只是在减的时候将结果除了个 4,所以结果仍然是 1。 ;(p+1)-p 0040106A mov ecx,dword ptr [ebp-10h] 0040106D add ecx,4 00401070 sub ecx,dword ptr [ebp-10h] 00401073 sar ecx,2 00401076 push ecx 【后记】 这些以前都有点印象,但是不是十分确定,昨天就试验了一下,找出了一下规律。其实这些 C99 上应该都有的,我同学正在帮我找,找到了将链接贴到这里。 When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements. (结果是两个数组元素的下标之差) From:http://blog.csdn.net/evers/articles/193603.aspx
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值