今天闲着无聊,逛了一下别人的blog~发现了这么一道题,我郁闷了,做错了~~晕死~
- #include <stdio.h>
- int main()
- {
- int a[5] = {1, 2, 3, 4, 5};
- int *pa = (int)(&a) + 1;
- printf("%x/n", *pa);
- return 0;
- }
你觉得答案会是多少涅?
哈哈,没错了,就是2000000!,如果你知道是这个数了,那么请你离开吧,别浪费时间了,你想的是对的!带着你的不屑去看大牛的文章吧
看到这里的人,估计都跟我一样,算错了吧~哈,那就多担待,看看我废话吧!
首先,考查点:一看到这样的题,我想到的是内存的分配图,字节对齐,字节序等问题。
所以我们应该先假定这程序运行的平台,假设该程序运行在intel 32位机上吧,那么我们就可以确定以下几个事:
1 int 是32位的
2 字节序是小端字节序(小端不知道的,自已查去!)
(&a)这个值求的是字符串的地址,即字符串的首地址,但又与a这个字符串的首地址有所差别@
把该地址值强制转化为int型,再把int型的数+1,把该值赋值给pa指针,即此时,该pa指针,指的就是a[0]的第二个字节的地址!
由于pa是整数指针,所以*pa的值就等于,a[0]字节的第二个字符起到a[1]的第1个字节组合而成的整数!
内存分布图如下:
|
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位机上的测试!