基本上我很难理解这一点:(来自 Bjarne FAQ)
然而,大多数现代处理器不能读取或写入单个字符,它必须读取或写入整个单词,因此对 c 的赋值实际上是“读取包含 c 的单词,替换 c 部分,然后再写回单词”。 ' 因为对 b 的赋值是相似的,所以两个线程有很多机会互相破坏,即使线程不(根据它们的源文本)共享数据!
那么 char 数组如何在元素之间没有 3(7?)字节填充的情况下存在?
基本上我很难理解这一点:(来自 Bjarne FAQ)
然而,大多数现代处理器不能读取或写入单个字符,它必须读取或写入整个单词,因此对 c 的赋值实际上是“读取包含 c 的单词,替换 c 部分,然后再写回单词”。 ' 因为对 b 的赋值是相似的,所以两个线程有很多机会互相破坏,即使线程不(根据它们的源文本)共享数据!
那么 char 数组如何在元素之间没有 3(7?)字节填充的情况下存在?
我认为 Bjarne 对此是错误的,或者至少,他大大简化了事情。大多数现代处理器能够
在不先读取完整字的情况下写入一个字节,或者更确切地说,它们的行为“好像”是这种情况。特别是,如果您有char array[2];
, 并且线程一仅访问array[0]
并且线程二仅访问array[1]
(包括当两个线程都在改变值时),那么您不需要任何额外的同步;这是由标准保证的。如果硬件不允许直接这样做,编译器将不得不自己添加同步。
注意上面的“好像”非常重要。现代硬件确实通过高速缓存行而不是字节来访问主存。但它也有修改缓存行中的单个字节的规定,这样当回写时,处理器核心不会修改其缓存中尚未修改的字节。
支持 C++11 的平台必须能够访问大小为 1 的存储,char
而无需发明写入。x86 确实有这种能力。如果一个处理器必须随时修改 32 位,它必须有一个 32 位宽的char
.
(一些背景推理:数组是连续存储的,字符没有填充(3.9.1)。)