目录:
一、C语言结构体的内存空间分配原理
1、什么是内存对齐
2、结构体内存对齐规则
3、范例
4、注意的问题
5、其它
二、结构体数组与指针
1、结构体数组
-----------------------------------------------------------------------------------------------------------------------
一、C语言结构体的内存空间分配原理
1、什么是内存对齐
假设我们同时声明两个变量:
char a;
short b;
用&(取地址符号)观察变量a,b的地址的话,我们会发现(以16位CPU为例):
如果a的地址是0x0000,那么b的地址将会是0x0002或者是0x0004。
那么就出现这样一个问题:0x0001这个地址没有被使用,那它干什么去了?答案就是它确实没被使用。因为CPU每次都是从以2字节(16位CPU)或是4字节(32位CPU)的整数倍的内存地址中读进数据的。如果变量b的地址是0x0001的话,那么CPU就需要先从0x0000中读取一个short,取它的高8位放入b的低8位,然后再从0x0002中读取下一个short,取它的低8位放入b的高8位中,这样的话,为了获得b的值,CPU需要进行了两次读操作。
但是如果b的地址为0x0002,那么CPU只需一次读操作就可以获得b的值了。所以编译器为了优化代码,往往会根据变量的大小,将其指定到合适的位置,即称为内存对齐(对变量b做内存对齐,a、b之间的内存被浪费,a并未多占内存)。
-----------------------------------------------
2、结构体内存对齐规则
结构体所占用的内存与其成员在结构体中的声明顺序有关,其成员的内存对齐规则如下:
1)每个成员分别按自己的对齐字节数和PPB(指定的对齐字节数,32位机默认为4)两个字节数最小的那个对齐,这样可以最小化长度。
2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度。
3)结构体对齐后的长度必须是成员中最大的对齐参数(PPB)的整数倍,这样在处理数组时可以保证每一项都边界对齐。
4)计算结构体的内存大小时,应该列出每个成员的偏移地址,则其长度=最后一个成员的偏移地址+最后一个成员数的长度+最后一个成员的调整参数(考虑PPB)。
下面举例说明上述规则:
#include "stdio.h"
#pragma pack(2)
//指定PPB为2
struct T
{
char a; //偏移地址0
int b; //偏移地址2
char c; //偏移地址6
};
#pragma pack()
//恢复原来默认PPB,32位下为4
struct T TestData;
int main(int argc,char *
argv[])
{
TestData.a=1;
TestData.b=260;
printf("%d\n",sizeof(struct T));
printf("%d\n",&TestData.a);
printf("%d\n",TestData.a);
return 0;
}
最后输出的结果为:8。语句#pragma
pack(2)的作用是指定结构体按2字节对齐,即PPB=2。分析如下:
变量a默认为1字节,PB=2,所以a按1字节对齐,a的偏移地址为0。
变量b默认为4字节(在32位机器中int为4字节),PB=2,所以b按2字节对齐,b的偏移地址为2。
变量c默认为1字节,PB=2,所以c按1字节对齐,偏