一、结构体的声明
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
struct 结构体名字 {
类型 名字;
类型 名字;
类型 名字;
...
}结构体变量1,结构体变量2……;
二、结构体内存对齐
1、为什么存在内存对齐?
1)平台原因(移植原因)︰不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2)性能原因︰数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
总体来说:
结构体的内存对齐是拿空间来换取时间的做法。
2、对齐规则是什么呢?
首先,我们得弄清楚以下四个值:
1)基本类型对齐值:自身大小;
2)自定义类型的自身对齐值:内部成员中最大的那个;
3)程序指定对齐值:#pragma pack(数值),其中,该数值必须为2的幂次方;
4)自定义类型的有效对齐值:就是在程序指定对齐值和自定义类型的自身对齐值中进行比较选择较小者。
然后,进行以下步骤:
1)先里再外,依次处理;
2)在类型后面标出相应的大小;
3)确定自定义类型的有效对齐值;
4)(1)若无程序指定对齐值,则上一个类型大小之和必须为下一个类型的整数倍,在不成立的后面进行相应的加法,直到最后一个数也处理完;
(2)若有程序指定对齐值,则确定自定义类型的有效对齐值,比较的类型大小必须为自定义类型的有效对齐值的整数倍,在不成立的后面进行相应的加法,直到最后一个数也处理完;
5)将4)步骤处理的值加起来看看是不是自定义类型的有效对齐值的整数倍。若不是,则在加上相应的数变为整数倍。
6)最后5)中确定的加起来的数就是我们的结构体内存对齐值。
注意:
1)若里面结构体类型包含数组,它的大小依旧是类型大小×数组大小,但是它的对齐值一直为自身类型得到大小。
例如:double c[10];//大小为80,但是对齐值为8
2)如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
三、实例
1、
typedef struct{
int a;//4
char b;//1+1
short c;//2
short d;//2因为4+1+1+2+2=10不是4的倍数,所以得再+2,即最终结果为12.
}AA_t;
这个结构体所占的空间大小是(12)字节
typedef struct Test//先看里面的,再看外面
{
short a;//2+6
struct
{
int b;//4+4
double c;//8
char d;//1因为4+4+8+1=17不是8的倍数,所以得再+7,
};//这个结构体类型的对齐值为8
int e;//4+4
}Test;
这个结构体所占的空间大小是(40)字节
#pragma pack(2)//程序指定对齐值为2
typedef struct Test
{
short a;//2
struct
{
int b;//4
double c;//8
char d;//1+1
};//这个结构体类型的对齐值为8,所以自定义类型的有效对齐值为2
int e;//4 因为2+4+8+1+1+4=20是2的倍数
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
这个结构体所占的空间大小是(20)字节
typedef struct Test
{
short a;//2+6
struct
{
int b;//4+4
double c[10];//大小为80,对齐值为8
char d;//1+7
};
int e;//4+4
}Test;
这个结构体所占的空间大小是(112)字节