结构体内存对齐规则详解

发布时间:2023-05-21

一、对齐规则简介

在计算机存储中,为了更加高效地利用内存,系统中的变量存储并不是随意进行的,而是要遵循特定的对齐规则。对齐规则指定了变量存储在内存中的起始地址必须是特定倍数的地址,这个倍数称为对齐值。常见的对齐值包括 1、2、4、8 等。 在结构体中,对齐规则同样适用,结构体存储内存的起始地址必须是结构体中占用空间最大的成员大小的倍数。

二、对齐规则的好处

对齐规则的实际目的是使得变量存储更加高效。使用对齐规则可以减少内存碎片的产生,而不使用对齐规则则可能会导致内存碎片的产生。 内存碎片是指内存中存在一些不连续的空间,这样使用内存时就需要分配多个不连续的内存块,导致内存利用率下降,而使用对齐规则可以减少内存碎片的产生,提高内存利用率。

三、对齐规则的实现

对齐规则的实现是通过在变量存储时添加一些额外的字节来实现的,这些字节称为补齐字节。补齐字节的数量由对齐值和变量的大小决定。 下面是一个简单的例子,假设我们有这样一个结构体:

struct MyStruct {
    char a;
    int b;
    char c;
};

其中 char 类型占用一个字节,int 类型占用四个字节。为了保证对齐,我们需要在变量存储时添加一些额外的字节,调整结构体内存的布局,如下图所示:

struct MyStruct {
    char a;
    char _pad[3];
    int b;
    char c;
};

在这个例子中,变量 ab 分别是 1 字节和 4 字节,它们的对齐值是 1 和 4,因此对齐值为 4,结构体中内存对齐的起始地址就必须是 4 的倍数。为了满足这个要求,我们需要在变量 a 后面补齐 3 个字节,使得变量 b 存储的起始地址是 4 的倍数。

四、对齐规则的影响

对齐规则的实现会产生一些影响,下面我们介绍一下结构体内存对齐规则可能产生的影响。

1. 结构体大小

对齐规则会影响结构体的大小。一般来说,结构体的大小是其成员占用空间之和,但由于结构体内存对齐规则的存在,可能会出现一些额外的空间,因此结构体的大小并不等于其成员占用空间之和。 下面我们还是以刚才的结构体为例,计算一下其大小:

struct MyStruct {
    char a;
    char _pad[3];
    int b;
    char c;
};

由于 a 占用 1 个字节,b 占用 4 个字节,c 占用 1 个字节,因此结构体的大小应该是 6 个字节。但是我们添加了 3 个字节的补齐,因此实际上结构体的大小是 12 个字节。

2. 访问速度

对齐规则还会影响结构体访问的速度。如果结构体成员没有按照对齐规则进行排列,那么访问这个成员的速度将会变慢。

五、代码示例

下面是一个代码示例,演示了结构体内存对齐规则的基本用法:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
struct MyStruct {
    char a;
    char _pad[3];
    int b;
    char c;
};
int main() {
    printf("sizeof(MyStruct) = %zu\n", sizeof(struct MyStruct));
    struct MyStruct s;
    s.a = 'a';
    s.b = 0x12345678;
    s.c = 'c';
    printf("&s = %p\n", &s);
    printf("&s.a = %p, s.a = %c\n", &(s.a), s.a);
    printf("&s.b = %p, s.b = 0x%x\n", &(s.b), s.b);
    printf("&s.c = %p, s.c = %c\n", &(s.c), s.c);
    return 0;
}

运行结果如下:

sizeof(MyStruct) = 12
&s = 0x7ffe8442dcbf
&s.a = 0x7ffe8442dcbf, s.a = a
&s.b = 0x7ffe8442dcc0, s.b = 0x12345678
&s.c = 0x7ffe8442dcc4, s.c = c