有什么内存地址空间?

Eri*_*hil 20 c c++ computer-architecture memory-address

使用了什么形式的内存地址空间?

今天,大型扁平虚拟地址空间很常见.从历史上看,已经使用了更复杂的地址空间,例如一对基地址和偏移量,一对段号和一个偏移量,一个字地址加上一个字节或其他子对象的索引,依此类推.

不时,各种答案和评论声称C/C++指针本质上是整数.这是一个不正确的C/C++模型,因为各种地址空间无疑是一些关于指针操作的C规则的原因.例如,不在数组之外定义指针算法简化了对基本和偏移模型中指针的支持.指针转换的限制简化了对地址加额外数据模型的支持.

这种反复出现的断言激发了这个问题.我正在寻找有关各种地址空间的信息,以说明C/C++指针不一定是一个简单的整数,并且考虑到要支持的各种机器,C/C++对指针操作的限制是明智的.

有用的信息可能包括:

  • 具有各种地址空间和这些空间的描述的计算机体系结构的示例.
  • 在当前正在制造的机器中仍在使用的各种地址空间的示例.
  • 引用文档或解释,尤其是URL.
  • 详细说明地址空间如何激发C/C++指针规则.

这是一个广泛的问题,所以我愿意接受有关管理它的建议.我很高兴看到一个通用包容性答案的协作编辑.然而,这可能无法授予应得的声誉.我建议投票多个有用的贡献.

Jam*_*nze 17

你可以想象的任何东西都可能被使用过.第一个主要部门是字节寻址(所有现代架构)和字寻址(IBM 360/PDP-11之前,但我认为现代Unisys大型机仍然是字处理的).在字寻址,char*并且void*往往会比一个大int*; 即使它们不是更大,"字节选择器"也将是高位,它们必须是0,否则将被忽略除字节以外的任何东西.(例如,在PDP-10上,如果p是a char*,则(int)p < (int)(p+1)通常是假的,即使int并且char*具有相同的大小.)

在字节寻址机器中,主要变体是分段和非分段架构.今天两者仍然广泛传播,尽管在英特尔32位(具有48位地址的分段架构)的情况下,一些更广泛使用的操作系统(Windows和Linux)人为地将用户进程限制为单个段,模拟平面寻址.

虽然我没有最近的经验,但我希望嵌入式处理器的种类更多.特别是,在过去,嵌入式处理器经常使用哈佛架构,其中代码和数据位于独立的地址空间中(因此,函数指针和数据指针,转换为足够大的整数类型,可以比较相等) ).


Nem*_*emo 5

我会说你问的是错误的问题,除了历史的好奇心.

即使你的系统碰巧使用了一个扁平的地址空间 - 事实上,即使从现在到结束的每个系统使用一个扁平的地址空间 - 你仍然不能将指针视为整数.

C和C++标准使各种指针算术"未定义".在任何系统上,这都会对您产生影响,因为编译器会假设您避免未定义的行为并相应地进行优化.

举个具体的例子,三个月前Valgrind出现了一个非常有趣的错误:

http://comments.gmane.org/gmane.comp.debugging.valgrind.devel/19698

(搜索"未定义的行为".)

基本上,Valgrind使用小于和大于指针来尝试确定自动变量是否在一定范围内.因为不同聚合中指针之间的比较是"未定义的",所以Clang只是优化了所有比较以返回常量true(或假;我忘了).

这个bug本身产生了一个有趣的StackOverflow问题.

因此,虽然原始指针算术定义可能适用于真实机器,并且这可能是有趣的,但它实际上与今天的编程无关.今天相关的是你不能假设指针的行为像整数,句点,无论你碰巧使用什么系统."未定义的行为"并不意味着"有趣的事情发生"; 这意味着编译器可以假设您不参与其中.当你这样做时,你会在编译器的推理中引入矛盾; 从矛盾来看,任何事情都随之而来......它只取决于你的编译器有多聪明.

而且他们总是变得更聪明.