命名空间
变体
操作

内存模型

来自 cppreference.cn
< c‎ | 语言

定义了计算机内存存储的语义,以用于 C 抽象机。

C 程序可用的数据存储(内存)是一个或多个连续的字节序列。内存中的每个字节都有一个唯一的地址

目录

[编辑] 字节

一个字节是内存中最小的可寻址单位。它被定义为连续的位序列,其大小足以容纳基本执行字符集的任何成员(96 个字符,它们被要求是单字节的)。C 支持 8 位及更大尺寸的字节。

类型 charunsigned charsigned char 在存储和值表示上都使用一个字节。一个字节中的位数可以通过 CHAR_BIT 访问。

关于字节用于表示其他基本类型的值(包括大端和小端内存布局),请参见对象表示

[编辑] 内存位置

一个内存位置

  • 标量类型(算术类型、指针类型、枚举类型)的对象
  • 或非零长度的位字段的最大连续序列
struct S
{
    char a;     // memory location #1
    int b : 5;  // memory location #2
    int c : 11, // memory location #2 (continued)
          : 0,
        d : 8;  // memory location #3
    struct
    {
        int ee : 8; // memory location #4
    } e;
} obj; // The object 'obj' consists of 4 separate memory locations

线程和数据竞争

执行线程是程序内的一个控制流,始于通过 thrd_create 或其他方式调用顶层函数。

任何线程都可以潜在地访问程序中的任何对象(具有自动和线程局部存储期的对象仍然可以通过指针被另一个线程访问)。

不同的执行线程总是被允许并发地访问(读取和修改)不同的内存位置,而没有干扰和同步要求。(注意,如果结构中声明在两个非原子位字段之间的所有成员也是(非零长度)位字段,则并发更新它们是不安全的,无论这些中间位字段的大小如何)

当表达式的求值写入一个内存位置而另一个求值读取或修改相同的内存位置时,这些表达式被称为冲突。具有两个冲突求值的程序存在数据竞争,除非

  • 两个冲突的求值都是原子操作
  • 其中一个冲突求值发生在另一个冲突求值之前(参见memory_order

如果发生数据竞争,程序的行为是未定义的。

(特别是,mtx_unlock 与同一互斥体的另一个线程的 mtx_lock 同步,因此发生在之前,这使得可以使用互斥锁来防范数据竞争)

内存顺序

当一个线程从内存位置读取值时,它可能会看到初始值、同一线程中写入的值或另一个线程中写入的值。有关从线程进行的写入对其他线程可见的顺序的详细信息,请参见memory_order

(C11 起)

[编辑] 参考文献

  • C23 标准 (ISO/IEC 9899:2024)
  • 3.6 字节(p: 待定)
  • 3.14 内存位置(p: 待定)
  • 5.1.2.4 多线程执行和数据竞争(p: 待定)
  • C17 标准 (ISO/IEC 9899:2018)
  • 3.6 字节(p: 待定)
  • 3.14 内存位置(p: 待定)
  • 5.1.2.4 多线程执行和数据竞争(p: 待定)
  • C11 标准 (ISO/IEC 9899:2011)
  • 3.6 字节(p: 4)
  • 3.14 内存位置(p: 5)
  • 5.1.2.4 多线程执行和数据竞争(p: 17-21)
  • C99 标准 (ISO/IEC 9899:1999)
  • 3.6 字节(p: 4)
  • C89/C90 标准 (ISO/IEC 9899:1990)
  • 1.6 术语定义

[编辑] 另请参见

C++ 文档 关于 内存模型