结构体与内存对齐

来源:互联网 发布:幼儿园美工室布置图片 编辑:程序博客网 时间:2024/06/16 01:18

在用sizeof运算符求一个结构体所占的空间时,并不是简单地将结构体中所有元素各自的空间相加,这里涉及到内存字节对齐的问题。理论上来说,对于任何变量的访问都可以从任何地址开始访问,但是,事实上不是如此,实际上访问特定类型的变量只能在特定的地址访问,这就需要各个变量在空间上按一定的规则排列,而不是简单地顺序排列,这就是内存对齐。

内存对齐的原因:

为了提高内存读写效率,CPU将内存分成多个块,每次从内存中读取一个块,这个块的大小可能是248等。CPU在访问内存的时候,每次读取一定长度,这个长度是系统默认的对齐数,如果没有对齐,为了访问一个变量可能产生二次访问。

内存对齐的规则:

1.数组成员对齐规则。第一个数组成员应该放在offset0的地方,以后每个数组成员应该放在 当前成员整数倍的地方开始。比如,int型占4字节,#pargama pack(2),那么从2倍数的地方开始存储。

2.结构体的总大小,一定是结构体内部最大成员的整数倍,不足要补齐。

3.结构体作为成员的对齐规则,如果一个结构体B中嵌套另一个结构体A,还是以最大成员类型的大小对齐,但是结构体A的起点为A内部最大成员的整数倍的地方。比如sizeof(struct A)=8,结构体B中存有A,那么结构体B开始存储的起始地址一定是8的整数倍。

4.手动设置对齐数

#pragma pack(show)warning message的形式显示当前packing alignment的字节数

#pragma pack(push)将当前指定的packing alignment数组进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignmentn。如果n没有被指定,则将当前的packing alignment数组压栈。

#pragma pack(pop)

internal compiler stack中删除最顶端的reaord,如果没有指定n,则当前栈顶record即为新的packing alignment数值,如果指定了n,则n成为新的packing alignment

#packing pack(n)

指定packing的数值,以字节为单位,缺省数值是8,合法的值分别有1,2,4,8,16


示例:

#include<stdio.h>
#include<stddef.h>
#include<stdlib.h>
#pragma pack(show)
typedef struct stu
{
int age;
double score;
char name[20];
}STU;
typedef struct teacher
{
char duty[12];//13,64;12;56
int class;
STU student;
}TEAC;
struct  hh
{
char ch;
int a;
int b;
};
void test()
{
STU stu1;
TEAC tea1;
printf("sizeof(stu):%d\n", sizeof(stu1));
printf("\noffsetof(STU,age):%d\n", offsetof(STU, age));
printf("offsetof(STU,score):%d\n", offsetof(STU, score));
printf("offsetof(STU,name):%d\n", offsetof(STU, name));
printf("--------------------------------------------\n");
printf("\nsizeof(tea1):%d\n",sizeof(tea1));
printf("\noffsetof(TEAC,duty):%d\n", offsetof(TEAC, duty));
printf("offsetof(TEAC, class):%d\n", offsetof(TEAC, class));
printf("\noffsetof(TEAC,student):%d\n", offsetof(TEAC, student));

}
void test01()
{
struct hh h1;
printf("sizeof(h1)=%d\n", sizeof(h1));
printf("offsetof(h1,a)=%d\n", offsetof(struct hh, a));
}
int main()
{
test01();
system("pause");
return 0;

}

0 0