【C语言 结构体联合体】字节对齐与字节大小计算

一、结构体的字节对齐与字节大小计算
1.1 结构体字节对齐的规则
1.2 示例解释
1.3 结论

二、联合体的字节对齐与字节大小计算
2.1联合体的对齐规则:
2.2 示例解释
2.2.1 实例1
2.2.2实例2
2.3 总结

三、结构体对齐基本规则

✨注意✨:先进行字节对齐,然后进行所占字节大小的计算。

一、结构体的字节对齐与字节大小计算

结构体字节对齐,以最长的那个为标准?

不是总是以最长的成员为标准,而是根据编译器的默认规则和对齐原则。以下是具体规则:


1.1 结构体字节对齐的规则
  1. 成员的对齐
    每个成员按照其类型大小对齐,例如:
    • char 对齐到 1 字节边界。
    • short 对齐到 2 字节边界。
    • intfloat 对齐到 4 字节边界。
    • double 对齐到 8 字节边界。
  2. 整体的对齐
    结构体的总大小必须是其最长对齐成员大小的倍数(或编译器指定的对齐参数)。
  3. 填充字节
    为了满足上述对齐规则,编译器会在必要时插入填充字节。
如果这没看懂,移步第三部分。

1.2 示例解释
typedef struct 
{
    
    
    short a;  // 2 字节
    char b;   // 1 字节
    int c;    // 4 字节
} Example;
  • 对齐分析
    • a 对齐到 2 字节边界,占 2 字节。s
    • b 紧接 a,但 char 对齐到 1 字节,仍占用 1 字节,编译器插入 1 字节填充
    • c 对齐到 4 字节边界,占 4 字节。
  • 总大小
    • 成员占用:2 + 1 + 1(填充) + 4 = 8 字节。
    • 总大小满足 4 字节对齐,所以结果为 8 字节

1.3 结论

字节对齐通常与最长的成员大小相关,但并非总是直接等于它,还取决于成员的顺序和编译器的设置。

二、联合体的字节对齐与字节大小计算

联合体(union)的字节对齐规则与结构体类似,但稍有不同,关键点如下:


2.1 联合体的对齐规则:
  1. 所有成员共享同一块内存
    联合体的大小由最大成员的大小决定,因为所有成员都存储在同一块内存中。
  2. 对齐按最大成员的对齐要求
    联合体的对齐方式是其最大成员的对齐要求(字节边界)。编译器会根据这个要求插入填充字节,使联合体的大小满足对齐要求。
  3. 总大小是最大对齐单位的倍数
    为了确保对齐,联合体的总大小会向上取整,成为最大对齐单位的倍数。

2.2 示例解释
2.2.1 实例1
typedef union {
    
    
    char a;       // 1 字节
    int b;        // 4 字节
    double c;     // 8 字节
} ExampleUnion;
  • 对齐分析:
    • 成员 a 需要 1 字节对齐,占 1 字节。
    • 成员 b 需要 4 字节对齐,占 4 字节。
    • 成员 c 需要 8 字节对齐,占 8 字节。
  • 联合体大小:
    • 最大成员 c 占用 8 字节,且对齐要求为 8 字节。
    • 联合体的大小为 8 字节(无额外填充,因为已经满足 8 字节对齐)。

2.2.2 实例2

再看一个复杂点的例子:

typedef union {
    
    
    short a;       // 2 字节
    char b[3];     // 3 字节
    int c;         // 4 字节
} ExampleUnion2;
  • 对齐分析
    • 成员 a 需要 2 字节对齐,占 2 字节。
    • 成员 b[3] 需要 1 字节对齐,占 3 字节。
    • 成员 c 需要 4 字节对齐,占 4 字节。
  • 联合体大小
    • 最大成员是 c,占 4 字节,对齐要求为 4 字节。
    • 联合体的大小为 4 字节(不需要额外填充)。

2.3 总结

对于联合体:

  • 大小 = 最大成员的大小(加上必要的填充以满足对齐)。
  • 对齐单位 = 最大成员的对齐要求。

三、结构体对齐基本规则

https://blog.csdn.net/qq_44443986/article/details/110082316

基本规则

规则1数据成员对齐规则

  • 结构体(struct)的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存放在offset为该数据成员大小的整数倍的地方。所以存在当前填充,确保下一位没错位。

  • 比如int在32位机为4字节,则要从4的整数倍地址开始存储。

规则2结构体大小规则

  • 结构体的总大小必须是其内部最大成员大小的整数倍。如果不是,编译器会在结构体末尾添加填充字节(padding)以满足这一规则

  • 结构体的总大小,也就是sizeof的结果,必须是其内部最大成员的整数倍,不足的要补齐。

规则3嵌套结构体对齐规则

  • 如果一个结构体B里嵌套另一个结构体A,则结构体A应从offset为A内部最大成员的整数倍的地方开始存储。

  • struct B里存有struct A,A里有char,int,double等成员,那A应该从8的整数倍开始存储。结构体A中的成员的对齐规则仍满足原则1、原则2。
    不是直接将结构体A的成员直接移动到结构体B中;

·
·
由于存储变量地址对齐的问题,计算结构体大小的3条规则:

1、结构体变量的首地址,必须是结构体变量中的“最大基本数据类型成员所占字节数”的整数倍。(对齐)
2、结构体变量中的每个成员相对于结构体首地址的偏移量,都是该成员基本数据类型所占字节的整数倍。(对齐)
3、结构体变量的总大小,为结构体变量中“最大基本数据类型成员所占字节数”的整数倍(补齐)