2008年1月20日星期日

结构体到底有多大?

先看一个程序:

#include <stdio.h>
struct Data
{
short id;
double val;
};
int main(void) {
struct Data mydata = {0x123, 7.7};
unsigned char * cp = (unsigned char *) &mydata;
printf("%p: ", cp);

for(int i = 0; i < sizeof(mydata); ++i) {
printf("%02X ", *(cp + i));
}
putchar('\n');

return 0;
}

猜猜运行结果是啥?下面这个是一个可能的运行结果。
0022FF78: 23 01 40 00 00 30 40 00 CD CC CC CC CC CC 1E 40
数数看,居然发现,只有一个short和一个double成员的结构体居然有16字节!!
在32位系统中,short的长度为16位,也就是2字节;double的长度为64位,即8字节,加起来也就是10字节。
就算编译器在实现short的长度时把定义为32位长(4字节),那也只有12位,哪里来的16位的呢?Google了一番之后才知道,原来是编译器为了优化,对成员数据进行了“对齐”,也就是和最长的数据类型等长。传说这么做有利于CPU高效处理数据。(没有学过编译原理,懒得深入。)

也许你对这段数据中的那个“30 40”又犯迷糊了。其实,那是垃圾值,不用理。把short类型改为long long之后再次执行,就好了(因为long long类型也是8字节长,初始化的时候,把垃圾值置0了)。

还有一个奇怪的现象,就是在Windows平台上,程序每次执行时,首地址居然都不变!!!Linux下,每次执行,cp的值都会变化的。我试图在Windows下让这个首地址变化,因此运行了Eclipse——狂占内存的软件,关掉之后,再次执行,结果地址依然不变。 -_____-||| 太恐怖了。

对Windows的内存管理我并不很清楚,但是回头想想,这也许是Windows为了提高软件热启动速度而出的招——保留刚关闭的程序使用的内存地址一段时间,以加速其热启动。甚至是在我用优化大师的内存整理程序整理了内存之后,这个地址依然如故,真是让人惊讶。

谁懂Windows的内存管理机制呢?给我解释一下吧~~忘记说明了,我用的C编译器是gcc,Windows平台的来自MinGW Develop Studio,Linux平台为gcc 4.1。看来,我真得学学计算机组成原理和汇编语言了。

没有评论:

发表评论