一道c语言指针问题!

今天闲着无聊,逛了一下别人的blog~发现了这么一道题,我郁闷了,做错了~~晕死~

 

  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     int a[5] = {1, 2, 3, 4, 5};
  6.     int *pa = (int)(&a) + 1;
  7.     printf("%x/n", *pa);
  8.     return 0;
  9. }

 

 

你觉得答案会是多少涅?

哈哈,没错了,就是2000000!,如果你知道是这个数了,那么请你离开吧,别浪费时间了,你想的是对的!带着你的不屑去看大牛的文章吧

 

 

看到这里的人,估计都跟我一样,算错了吧~哈,那就多担待,看看我废话吧!

首先,考查点:一看到这样的题,我想到的是内存的分配图,字节对齐,字节序等问题。

所以我们应该先假定这程序运行的平台,假设该程序运行在intel 32位机上吧,那么我们就可以确定以下几个事:

1 int 是32位的

2 字节序是小端字节序(小端不知道的,自已查去!)

 

(&a)这个值求的是字符串的地址,即字符串的首地址,但又与a这个字符串的首地址有所差别@

把该地址值强制转化为int型,再把int型的数+1,把该值赋值给pa指针,即此时,该pa指针,指的就是a[0]的第二个字节的地址!

 

 

由于pa是整数指针,所以*pa的值就等于,a[0]字节的第二个字符起到a[1]的第1个字节组合而成的整数!

 

内存分布图如下:

 






A[0]0xbf9968ac01

0xbf9968ad00

0xbf9968ae00

0xbf9968af00

A[1]0xbf9968b002  pa

0xbf9968b100

0xbf9968b200

0xbf9968b300

A[2]0xbf9968b403

0xbf9968b500

0xbf9968b600

0xbf9968b700

A[3]0xbf9968b804

0xbf9968b900

0xbf9968ba00

0xbf9968bb00

A[4]0xbf9968bc05

0xbf9968bd00

0xbf9968be00

0xbf9968bf00




 

pa指向a[1] 的第一个字节[0xbf9968b0]

然后*pa即是取从该地址开始的四个字节所存储的内容,pa所指向的那个整数值,因为是小端字节序,所以02应在高位,所以该整数变为

02000000!

这就是为什么答案是02000000!明白了吧。

 

好吧,引申再复习下内存分配与指针的问题吧~

 

 

再看下面一个例子:

 

 

运行环境:gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5) 

运行结果如下:

 

 

 

从上面代码可得出:

1)该程序的所有变量存放在栈里,栈的分布情况是从高地址往低地址分布,

      注意:这里有一点需要关注一下,可能是编译器相关的问题,就是数组并不满足先定义先分配的规律,数组分布位置会在所有变量分布完

      后的后面分配;当x的地址却要比a数组的地址要高,因为x先定义,

       但after_array1的值也比a高!这里我也还没问明白,估计是编译器优化!

2)数组的内存分配是从低到高!即a[0]的地址比a[1]的地址要低。

3)int a[5]={...}

     定义该数组之后,a与&a数值相同,但表示的意义完全不一样,可从a+1,&a+1的值可以看出,a+1的步长是4个字节,而&a+1的步长      却是整个数组的长度。

4)内存字节序的问题,*(char *)((int)(&a) + x)从低地址到高地址每个字节的内容,注意:14存放的地址比11的地址要低,如果刚刚第一      个例子看得明白的话,这里应该也知道怎么来的了,包括最后一个输出的值,其实就是跟第一个例子是完全一样的!

     这里需要注意的是不能忘了把(&a)强制转化为int型,这里(&a)也可以替换为a,因为这里只需要的是该数组首地址这个“值”在这一点       上这两个是没有区别的!

 

最后,last but not least!

     上面所有的测试都是与平台相关的,如果是64位,或者是16位机那又要另当别论了,所以一开始我就是采用假设是在32位机上的测试!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值