Skip to content
📖 Auto 版 Modern C本书目录

第十二章:C 内存模型 ​

级别 2 — 认知

对象、字节、联合体、有效类型、对齐——最深的 C 内部机制。

这是本书技术密度最高的一章。C 内存模型定义了数据如何存储、访问和在字节级别解释。理解它对于编写正确的底层 C 以及欣赏 Auto 抽象了什么都至关重要。


12.1 统一内存模型 ​

在 C 中,所有数据——整数、浮点数、结构体、数组——都作为连续的字节序列存储。每个字节有唯一地址,内存中的每个对象都可以作为原始字节检查。

c
// C 深入:对象表示
int x = 42;
unsigned char *bytes = (unsigned char*)&x;
printf("Byte 0: 0x%02x\n", bytes[0]);
printf("Byte 1: 0x%02x\n", bytes[1]);
// 小端序:0x2a, 0x00(对于 int32)

关键概念:

  • 对象:保存特定类型值的存储区域。
  • 表示:编码该值的字节序列。
  • sizeof:对象占用的字节数。
c
// C 深入:常见类型的大小
printf("sizeof(char):   %zu\n", sizeof(char));   // 始终为 1
printf("sizeof(int):    %zu\n", sizeof(int));    // 通常为 4
printf("sizeof(float):  %zu\n", sizeof(float));  // 通常为 4
printf("sizeof(double): %zu\n", sizeof(double)); // 通常为 8
printf("sizeof(int*):   %zu\n", sizeof(int*));   // 4 或 8

类型的大小决定了指针算术前进多少字节。sizeof(char) 根据定义始终为 1——它是 C 中存储的基本单位。

C 深入: C 保证任何对象都可以使用 memcpy 逐字节复制。这是序列化和反序列化的基础。Auto 对其值类型提供相同的保证。


12.2 联合体 ​

联合体是一种所有成员共享相同内存位置的类型。联合体的大小等于其最大成员的大小:

c
// C 深入:联合体
union Value {
    int i;
    float f;
    char s[16];
};

union Value v;
v.i = 42;                // 以 int 存储
printf("%d\n", v.i);     // 以 int 读取:42
v.f = 3.14f;             // 以 float 覆盖
printf("%f\n", v.f);     // 以 float 读取:3.14
// printf("%d\n", v.i);  // 未定义行为:类型错误!

从非最后写入的成员读取在标准 C 中是未定义行为(符号变体有例外)。这使得裸联合体很危险。

标签联合体通过将判别符(标签)与联合体配对解决了这个问题:

c
// C 深入:标签联合体
enum ValueType { VAL_INT, VAL_FLOAT, VAL_STRING };

struct TaggedValue {
    enum ValueType tag;
    union {
        int i;
        float f;
        char s[16];
    } data;
};

void describe(struct TaggedValue v) {
    switch (v.tag) {
        case VAL_INT:    printf("integer: %d\n", v.data.i); break;
        case VAL_FLOAT:  printf("float: %f\n", v.data.f); break;
        case VAL_STRING: printf("string: %s\n", v.data.s); break;
    }
}

Auto 的替代:带数据的 enum。 Auto 将标签联合体作为一等特性提供,消除了手动管理:

auto
enum Value {
    IntVal int
    FloatVal float
    StrVal str
}

fn describe(v Value) str {
    is v {
        IntVal(n) => "integer: " + str(n)
        FloatVal(f) => "float: " + str(f)
        StrVal(s) => "string: " + s
    }
}

基于 MIT 许可发布。