本文讨论限制在VC++ 编译器
讨论对象:
#pragma pack([n])
1. 对齐原则为(参考百度百科#pragma pack词条):
编译器中提供了#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。
下面举例说明其用法。
#pragma pack(push) //保存对齐状态
struct test
{
char m1;
double m4;
int m3;
};
#pragma pack(pop)//恢复对齐状态
|
2. 内嵌结构体
#include <stdio.h>
typedef unsigned char UINT8;
typedef unsigned int UINT32;
#pragma pack(4)
typedef struct _xxx {
UINT8 a;
UINT32 b;
}xxx;
#pragma pack()
#pragma pack(2)
typedef struct _yyy {
UINT8 a;
xxx b; //这里的内存对齐怎么算???
} yyy;
#pragma pack()
void main()
{
yyy y;
yyy *py = &y;
xxx *px;
y.a = 1;
y.b.a = 2;
y.b.b = 3;
px = &y.b;
printf("%d-%d\n", px->a, px->b);
}
运行结果为
即:
结构体yyy 里xxx(b)的内部还是按xxx定义时的规则进行内存对齐. 然后在yyy里xxx(b)只是一个变量, 对齐要求为xxx里成员在对齐要求最大的数值做为xxx的对齐要求
再来一例, 注意看图片里红色方框里的cc(即未初始化的内容)
#include <stdio.h>
typedef unsigned char UINT8;
typedef unsigned int UINT32;
#pragma pack(4)
typedef struct _xxx {
UINT8 a;
UINT32 b;
UINT8 c;
}xxx;
#pragma pack()
#pragma pack(2)
typedef struct _yyy {
UINT8 a;
xxx b; //这里的内存对齐怎么算???
UINT8 c;
} yyy;
#pragma pack()
#pragma pack(1)
typedef struct _zzz {
UINT8 a;
yyy b;
UINT8 c;
} zzz;
#pragma pack()
void main()
{
zzz z[2];
yyy *py = &z[0].b;
z->a = 1;
z->b.a = 2;
z->b.b.a = 3;
z->b.b.b = 4;
z->b.b.c = 5;
z->b.c = 6;
z->c = 7;
memcpy(z+1, z, sizeof(zzz));
printf("%d-%d\n", py->a, py->b.a);
}