结构体内存分布
  前面在结构体定义时已经讲述过,编译器是根据定义结构体变量时根据其成员变量的大小来分配内存空间。结构体内存空间的分配情况,这里需要重点说明一下。因为软件编程中这关乎程序使用时所占用空间以及执行效率。结构体在内存中分配情况有一点可以确定,即编译器会保证其各个成员变量在内存中出现的位置顺序按照定义时的顺序依次存放,并且结构体第一个成员变量通常为整个结构体对象的首地址。
  计算机软件编程中需要关注内存对齐的概念,尤其是开发应用程序在不同平台移植情况下。计算机系统中为了保证处理器访问内存的高效,因此约定要求数据类型在内存空间中好能够按照自然边界对齐。所谓的自然边界首先为偶数地址,并且可以被4或8整除的地址。由于计算机处理器在访问自然边界对齐的内存区域只需要一次处理,而处理未对齐的内存区域可能需要两次访问。因此在各个程序语言编译器上都针对这种情况作了优化,C++编译器也针对此类情况在程序编译期作了优化。
  每个不同平台编译器都有其默认的对齐参数,供编译器在程序编译期间去优化所定义的数据类型的内存布局。C++编译同样也具有该默认对齐参数,经过查阅相关资料以及测试证实,32位Windows平台下C++编译器默认采用8字节对齐方式。而32位Linux平台下C++编译器默认采用4字节对齐处理方式。下面通过一个结构体内存分配实例验证两种不同平台下针对内存对齐的不同处理方式。
  struct Record //定义记录结构体Record
  {
  chardata1; //结构体数据成员data1,字符型变量
  doubledata2; //结构体数据成员data2,double类型变量
  intdata3; //结构体数据成员data3,整型变量
  };
  Record record; //记录结构体变量定义
  sizeof(record); //计算结构体变量大小
  以上实例代码在32位Windows操作系统VC++平台自带编译器下程序执行结果计算出该结构体长度为24个字节大小。而32位Linux平台C++编译器下程序执行结果该结构体大小为16字节,这种差异是由于两种不同平台下编译器默认设置差异引起的。Linux平台默认设置为4字节对齐,该结构体在内存中布局如下。
  char data1; //1字节大小,可以认为其偏移从0开始,data1数据在内存中位置为0
  double data2; //8字节大小,可以认为偏移从1~8
  int data3; //4字节大小,由于从9开始不能够被4整除,则后移至12位置,从12~16
  32位Linux平台下以上数据在内存中假设存放的偏移从位置0开始,单个字节表示逐个递增。由于该结构体变量首地址为第一个数据成员地址,该成员为char型数据大小为1个字节,所以可以认为其偏移量为0。第二个double类型数据大小为8个字节,偏移位置从1~8位置,其起始位置都可以被4整除。
  因此到目前为止编译器应该并没有对数据存放位置作优化,第三个数据为整型大小为4个字节,偏移位置应从9开始。由于该起始偏移位置不能被4整除,故编译器需要作出填充使得该数据从12偏移位置开始到16为结束。终计算出整个结构体数据大小为16字节。Windows平台下依然可以按照此方式理解。
  C++编译器中也提供选项设置来修改内存对齐参数,通常可以使用如下程序命令来设置该参数。
  #pragma pack(n) //n表示设置几字节对齐
  以上设置方式修改了编译器默认对齐参数,其中n表示以几字节对其方式优化数据类型成员内存布局。同样上述实例如果在设置对齐字节为1时,终计算该结构体大小为13字节,即每个成员都是以紧凑无空隙的方式被分配内存。C++中内存对齐完全理解清楚需要涉及非常底层且专业的深入研究,这里所讲述的布局方式也仅仅是建立在相关资料查阅以及实验验证的基础上作出的猜测。更多的测试总结规律还需要初学者随着不断深入学习,一种不断探寻真相的精神,继续下去。
  由于篇幅限制,C++中内存对齐概念只作出初略肤浅的讲述。随着在实践中不断深入相信会遇到与此有关的问题。尤其笔者在不同的UNIX平台下从事软件开发过程中,发现不同平台的UNIX可能会对内存管理作出一定的优化修改。因此造成的差异在平台应用程序移植中经常会遇到一些意想不到的问题,需要我们不断的深入学习并总结经验和规律。