首先说明使用的系统是32位的。
我们先看看下面这段简单的程序:
#include<stdio.h>
#include<string.h>
main()
{
struct{
char s;
short a;
}text;
text.s='s';
char *ptr=&text.s;
ptr[0]=30;
ptr[1]=128;
ptr[2]=128;
ptr[3]=255;
printf("ptr[*]=%d/n",ptr);
printf("ptr[0]=%d/n",&ptr[0]);
printf("ptr[1]=%d/n",&ptr[1]);
printf("ptr[2]=%d/n",&ptr[2]);
printf("ptr[3]=%d/n",&ptr[3]);
printf("-------------------/n");
printf("text addr=%d/n",&text);
printf("char addr=%d/n",&text.s);
printf("short addr=%d/n",&text.a);
printf("-------------------/n");
printf("char=%d/n",text.s);
printf("short=%d/n",text.a);
}
再看看运行结果:
看到结果会有点惊讶,但是分析一下就完全可以理解的了,下面看看分析为什么会有这样的结果。
首先输出的是ptr的首地址,接着输出prt[0],ptr[1]等的地址,由于ptr是字符型指针,它的首地址是2293620(随机分配的),而在32位的系统中,一个字符占1个字节,也即8位,而ptr[0]也即对应ptr的首地址2293620,前面说过ptr的基类型是字符占一个字节,所以ptr[1]的地址应该就是ptr[0]的地址加1个字节,也即2293621,以此类推。我们画出下面的地址分配图:
接着第二部分输出的是结构类型text的首地址,然后输出结构类型中的char类型成员的地址和short类型的地址,成员s的地址是2293620我们很容易理解,但是为什么short类型的a成员的起始地址是2293622呢?这主要是结构类型的内存空间大小分配问题,为了提高CPU的存储速度,VC对一些变量的起始地址做了”对齐”处理。
在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数,各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。
看看下面这个例子:
main()
{
struct{
char s;
short a;
double b;
}text1;
struct{
char s;
double a;
short b;
}text2;
printf("%d/n",sizeof(text1));
printf("%d/n",sizeof(text2));
}
输出结果是16和24,一个结构体有相同的成员,只是不同的成员顺序,结果相差那么多,看看分析:
第一个:1 1 2 8 4 à1+1+2+8+4=16
第二个:1 7 8 4 4 à1+7+8+4+4=24
具体过程就不分析了,参考http://blog.sina.com.cn/s/blog_4b839a1b0100bbh2.html,这里有更详细的说明。
现在知道成员s的地址空间范围是2293620~2293622,a成员的地址范围是2293622~2293624,为了不跑题太远,现在继续往下分析。
结构体text里面的s成员是占一个字节,所以prt[0]即为s的ascII值,ptr[1]在这里被抛弃了。下面就是要分析比较重点的地方,前面分析过,成员a占两个字节,也即a的空间是ptr[2]和ptr[3]的组合空间,a的起始地址是ptr[3]的首地址。ptr[2]=128,ptr[3]=255,那么为什么a的值会是-128呢?组合ptr[2]和ptr[3]的地址然后把他们用二进制表示,如下:
00000001 1111111 1
ptr[2] ptr[3]
由于计算机里面是用补码表示的,而且在short类型的最右边的那位是表示整数的符号(正负),很明显这里为1,所以表示的是负数。负数的原码是补码取反再加1(符号位(最右边的那个1)不参与),所以我们可以得到一下原码:
00000001 1111111 1---取反-->11111110 0000000 1----加1-->00000001 0000000 1
根据上面的结果我们就可以知道这个数的绝对值是128,因为是负数,所以更正为-128.
由上面的分析我们也可以看出:现在用的这台电脑是小端的,也就是说低地址中存放的是字数据的低字节,高地址存放的是字数据的高字节。