结构体、位域、栈的字节对齐

为什么要字节对齐

可移植性:不是所有硬件都能从任意地址开始访问数据,如 MIPS 遇到未对齐内存直接报错
效率:CPU 每次读取内存时是一块一块读取的,如果目标数据跨越了两个块,CPU 要把两个块都读进来,去掉无关字节,然后将两个块中的目标数据拼接起来,大大降低了 CPU 的效率


结构体/联合体中的字节对齐

结构体内的第一个成员的偏移量为0,此后每个成员的偏移量为 min(#pargma pack(),成员自身长度)的倍数
对于联合体,每个成员的偏移地址都是0

如果结构体中嵌套结构体/联合体,那么嵌套的结构体/联合体的偏移量必须是它最大成员的字节数的整数倍

最后,结构体/联合体总的字节数必须是最宽基本类型成员所占字节数的整数倍(包括嵌套的结构体中的基本成员)

struct outer {
    int a;
    struct {
    	double d;
        char c;
        int i;
    }in;
};
//sizeof(struct outer) == 24  sizeof(struct inner) == 16

struct outer {
    int a;
    union inner{
    	double d;
        char c;
        int i;
    }s;
};
//sizeof(struct outer) == 16  sizeof(union inner) == 8

union outer {
    int a;
    union inner{
    	double d;
        char c;
        int i;
    }s;
};
//sizeof(union outer) == 8  sizeof(union inner) == 8

位域的压缩与字节对齐

首先简单介绍一下位域(bit filed、位段)
位域用于声明将数据以位的形式紧凑储存,并允许直接对位域变量进行操作
位域类型变量不可取址
优点:①节省空间;②可以方便将一个整数值的部分位作为整体访问、操作
缺点:位域的压缩与对齐是平台、机器相关的,难以移植

位域的压缩:

  • 如果相邻位域字段的位域类型相同,各个字段只占定义时的位长度
  • 如果一个位域字段的长度压缩时会跨越两个位域类型存储单元,则对齐到第二个单元存储
  • 如果位域字段间有非位域字段,则这两个位域字段不进行压缩

位域的对齐:如果相邻的位域字段类型不同,则按照结构体对齐规则对位域类型进行对齐

位域就像,按位域类型正常分配空间,压缩性地使用部分空间

struct test{
    char c1:1;
    char c2:2;
    char c3:7;
    int  i:3;
    char c4:2;
};
//sizeof(struct test) == 12, c3从第二个字节开始, i从第五个字节开始, c4从第九个字节开始

调用栈的字节对齐

主要是为了支持 SSE(Streaming SIMD Extensions)浮点运算扩展指令集与16字节的 XMM 浮点寄存器
GCC 栈帧的边界默认以16字节对齐,栈帧内按正常规则对齐


编译器对字节对齐的支持

对于 VC 来说,有 #pargma pack(n) 预处理命令,如 #pargma pack(8),指定按照8字节对齐
#pargma pack(push) 、#pargma pack(pop) 保存当前字节对齐状态、弹出栈顶字节对齐状态
#pragma pack (),取消自定义字节对齐方式


对于GCC,除了 #pargma pack(n) 预处理命令外
还可以使用 __attribute__ 机制来指定字节对齐数,如在描述GDT表项的数据结构中,

struct gdt_entry {
    uint16_t limit_low;
    uint16_t base_low;
    uint8_t base_middle;
    uint8_t access;
    unsigned limit_high: 4;
    unsigned flags: 4;
    uint8_t base_high;
} __attribute__((packed));

attribute 中 packed 表明 struct / union 中的成员紧紧地打包在一起,不进行字节对齐(亲测 DEVC gcc,还是进行了对齐)
可以使用 aligned (alignment) 属性来指定字节对齐数
如 __attribute__((aligned(4))) 四字节对齐,__attribute__((aligned)) 默认对齐方式

此外,attribute 属性的效果与链接器也有关,attribute 属性指定的字节对齐数,需要链接器也支持


2019/12/22

原文地址:https://www.cnblogs.com/kafm/p/12721788.html