您的位置:首页 > 其它

结构体字节对齐

2013-06-24 21:54 274 查看
先看一段代码

#include <stddef.h>
#include <stdio.h>

//package size defaults to 8
struct E
{
int i; // size 4
short j; // size 2
double k; // size 8
};

#pragma pack(4)
struct F
{
int i;
short j;
double k;
};

#pragma pack(2)
struct T
{
int i;
short j;
double k;
};

struct struct_taga
{
char i;
short j;
};

#pragma pack(push, r2, 1)
struct struct_tagb
{
char i;
short j;
};

#pragma pack(push, 8)
struct struct_tagc
{
char i;
short j;
};

void main()
{
printf("%d ", offsetof(E, i));
printf("%d ", offsetof(E, j));
printf("%d\n", offsetof(E, k));
printf("%d ", offsetof(F, i));
printf("%d ", offsetof(F, j));
printf("%d\n", offsetof(F, k));
printf("%d ", offsetof(T, i));
printf("%d ", offsetof(T, j));
printf("%d\n", offsetof(T, k));

printf("sizeof(E) = %d\n", sizeof(E));
printf("sizeof(F) = %d\n", sizeof(F));
printf("sizeof(T) = %d\n", sizeof(T));

printf("sizeof(struct_taga) = %d\n", sizeof(struct_taga));
printf("sizeof(struct_tagb) = %d\n", sizeof(struct_tagb));
printf("sizeof(struct_tagc) = %d\n", sizeof(struct_tagc));
}0 4 8
0 4 8
0 4 6
sizeof(E) = 16
sizeof(F) = 16
sizeof(T) = 14
sizeof(struct_taga) = 4
sizeof(struct_tagb) = 3
sizeof(struct_tagc) = 4 
——————————————————————————————————————————————————

#pragma pack(n)

数据边界对齐方式:
以如下结构为例: struct {
                    char a;
                    WORD b;
                    DWORD c;
                    char d;
                   }
在Windows默认结构大小: sizeof(struct) = 4+4+4+4=16;
与#pragma pack(4)一样
若设为 #pragma pack(1), 则结构大小: sizeof(struct) = 1+2+4+1=8;
若设为 #pragma pack(2), 则结构大小: sizeof(struct) = 2+2+4+2=10;
在#pragma pack(1)时:空间是节省了,但访问速度降低了;

——————————————————————————————————————————————————
科普:

pack 为 struct, union 和 class 等的成员对齐指定字节边界. 与编译选项的 /Zp 开关不同, 它不针对整个项目, 而仅针对模块, 比如一个编译单元.
 
1. #pragma pack(show)
    以警告信息的形式显示当前字节对齐的值.
2. #pragma pack(n)
    将当前字节对齐值设为 n .
3. #pragma pack()
    将当前字节对齐值设为默认值(通常是8) .
4. #pragma pack(push)
    将当前字节对齐值压入编译栈栈顶.
5. #pragma pack(pop)
    将编译栈栈顶的字节对齐值弹出并设为当前值.
6. #pragma pack(push, n)
    先将当前字节对齐值压入编译栈栈顶, 然后再将 n 设为当前值.
7. #pragma pack(pop, n)
    将编译栈栈顶的字节对齐值弹出, 然后丢弃, 再将 n 设为当前值.
8. #pragma pack(push, identifier)
    将当前字节对齐值压入编译栈栈顶, 然后将栈中保存该值的位置标识为 identifier .
9. #pragma pack(pop, identifier)
    将编译栈栈中标识为 identifier 位置的值弹出, 并将其设为当前值. 注意, 如果栈中所标识的位置之上还有值, 那会先被弹出并丢弃.
10. #pragma pack(push, identifier, n)
    将当前字节对齐值压入编译栈栈顶, 然后将栈中保存该值的位置标识为 identifier, 再将 n 设为当前值.
11. #pragma pack(pop, identifier, n)
    将编译栈栈中标识为 identifier 位置的值弹出, 然后丢弃, 再将 n 设为当前值. 注意, 如果栈中所标识的位置之上还有值, 那会先被弹出并丢弃.
   
注意: 如果在栈中没有找到 pop 中的标识符, 则编译器忽略该指令, 而且不会弹出任何值.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: