Why do atoms start at 0xC000? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080429-00/?p=22543
Raymond Chen 2008年04月03日
有两种类型的原子,即所谓的整数原子,它们只是一些小整数,还有就是没有特别形容词的原子;这些普通的原子来自像AddAtom
这样的函数。(为了本次讨论,我将称它们为字符串原子。)原子零是无效的(INVALID_ATOM
);从1到MAXINTATOM-1
的原子是整数原子,从MAXINTATOM
到0xFFFF
的原子是字符串原子。为什么MAXINTATOM
的值是0xC000
?
这个原因根植于16位Windows系统。原子存储在一个原子表中。原子表的细节并不重要,除了原子表中的节点是从堆分配的,每个节点对应于该原子表中的一个字符串。
由于我们是在16位Windows下工作,原子表中的指针是16位指针,16位堆中的所有内存块都是4字节对齐的。4字节对齐意味着地址的最低两位始终为零。因此,节点指针中只有14位是有效的。取这个指针,右移两位,设置最高两位,你就得到了你的原子。相反,要将原子转换回节点,去掉最高两位,并将结果左移两位。
为什么要这样编码指针呢?嗯,你有14位信息,但你想返回一个16位的值。你有两个位可以操作,所以你的决策是这些位应该放在哪里以及它们应该有什么值。如果所有的整数原子都是连续的,所有的字符串也是连续的,那将使范围检查变得更容易。现在你只剩下两个选项。你有49152个值的范围用于整数原子,有16384个值的范围用于字符串原子。你要么把整数原子放在低端(0x0000-0xBFFF
),把字符串原子放在高端(0xC000-0xFFFF
),要么把字符串原子放在低端(0x0000-0x3FFF
),整数原子放在高端(0x4000-0xFFFF
)。你可能不希望零是一个有效的字符串原子,因为那是未初始化的原子变量最可能的值,所以把字符串原子放在范围的顶部是更好的。
现在,随着转换到Win32,旧的原子实现被抛弃了。原子不再编码指针,但新的实现仍然必须遵守将16位原子空间分解为整数原子和字符串原子的规则。
在接下来的几篇文章中,我们将探讨字符串原子分配方式的其他后果,以及你可以用原子做的一些令人惊讶的事情。(不一定是好事,但仍然令人惊讶。)