C 结构体对齐规则

  1. 描述指针与指针变量的区别:

    • 指针:指针是一个变量,它存储着内存中某个数据单元的地址,即内存单元的编号。
    • 指针变量:指针变量本质上也是一个变量,但它存储的是另一个变量或者数据结构的地址,而不是实际的数据。
  2. 描述32位或64位平台下指针的大小:

    • 在32位平台上,任意类型的指针大小为4字节。
    • 在64位平台上,任意类型的指针大小为8字节。
  3. 描述指针数组的概念:

    • 指针数组是数组的一种,其中每个元素都是指针类型,即存储的是地址。这意味着指针数组中的每个元素都指向某个数据单元的地址。
  4. 描述define和typedef的区别:

    • #define 是 C 预处理指令,用于创建宏。它在编译之前执行文本替换。
    • typedef 是 C 语言关键字,用于为已有的数据类型创建一个新的名字。它在编译时期进行处理,可以提高代码的可读性和可维护性。
  5. 结构体对齐规则:

    • 规则一: 结构体中的元素按照定义的顺序依次置于内存中,但并不是紧密排列。每个元素被放置在其自身对齐大小的整数倍地址上。
    • 规则二: 如果结构体大小不是所有元素中最大对齐大小的整数倍,则结构体对齐到最大元素对齐大小的整数倍,填充空间放置到结构体末尾。
    • 规则三: 基本数据类型的对齐大小为其自身的大小,结构体数据类型的对齐大小为其元素中最大对齐大小元素的对齐大小。

这些规则确保了结构体在内存中的布局和访问时的一致性和效率。


详细解释结构体对齐规则:

结构体对齐规则是编译器为了最大化内存访问速度和最小化内存使用而采用的一种策略。这些规则确保了结构体在内存中的布局是可预测和高效的。

  1. 规则一:元素对齐

    • 结构体中的每个元素按照其自身的对齐要求被放置在内存中。对齐要求通常与元素的数据类型有关。
    • 基本数据类型的对齐要求通常是其自身大小,例如,int通常对齐到4字节边界,double通常对齐到8字节边界。
    • 结构体中的自定义类型(如结构体本身或者其他自定义类型)的对齐要求通常是其包含的基本数据类型中的最大对齐要求。
  2. 规则二:填充空间

    • 如果结构体中的元素的大小之和不是某个值的整数倍,编译器会在结构体的末尾插入一些填充空间,使得结构体的总大小是某个值的整数倍。
    • 这个值通常是结构体中的元素中的最大对齐要求。
  3. 结合示例详细解释: 假设有以下结构体:

    struct Example {
        char a;    // 1字节
        int b;     // 4字节(32位平台)
        double c;  // 8字节
    };
    
    • 结构体中的char类型通常对齐到1字节边界,所以a被放置在结构体的起始位置。
    • int类型通常对齐到4字节边界,所以b被放置在离结构体起始位置最近的4字节边界上,可能会有3个字节的填充空间。
    • double类型通常对齐到8字节边界,所以c被放置在离结构体起始位置最近的8字节边界上,可能会有4个字节的填充空间。
    • 结构体的总大小通常是8的整数倍,所以结构体的总大小可能是24字节(1字节的a + 3字节填充 + 4字节的b + 4字节的c)。

通过这些对齐规则,编译器可以确保结构体的访问速度是高效的,并且在不同的平台上,结构体的大小和布局都是可预测的。


代码解释一下这三个规则:

  让我们用一些 C 代码来演示这三个结构体对齐规则:

#include <stdio.h>

// 定义一个结构体
struct Example {
    char a;     // 1字节
    int b;      // 4字节(32位平台)
    double c;   // 8字节
};

int main() {
    printf("Size of struct Example: %zu bytes\n", sizeof(struct Example));
    printf("Offset of member 'a': %zu bytes\n", offsetof(struct Example, a));
    printf("Offset of member 'b': %zu bytes\n", offsetof(struct Example, b));
    printf("Offset of member 'c': %zu bytes\n", offsetof(struct Example, c));

    return 0;
}

运行这段代码,你会得到类似以下的输出(具体数值可能因编译器和平台而异):

Size of struct Example: 16 bytes
Offset of member 'a': 0 bytes
Offset of member 'b': 4 bytes
Offset of member 'c': 8 bytes

现在让我们解释这个输出以说明结构体对齐规则:

  1. Size of struct Example: 16 bytes

    • 结构体Example的大小为16字节。这是因为在32位平台上,char占1字节,int占4字节,double占8字节,加上填充字节。
  2. Offset of member 'a': 0 bytes

    • 成员a位于结构体的起始位置,因此其偏移量为0字节。
  3. Offset of member 'b': 4 bytes

    • 成员b被放置在离结构体起始位置最近的4字节边界上,因此它的偏移量为4字节。
  4. Offset of member 'c': 8 bytes

    • 成员c被放置在离结构体起始位置最近的8字节边界上,因此它的偏移量为8字节。

这个示例演示了结构体对齐规则,说明了每个成员在内存中的位置和结构体的总大小。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容