Oli*_*liv 26 c c++ pointers pointer-arithmetic language-lawyer
在C/C++中,仅当结果指针位于原始指向的完整对象内时,才定义指针的加法或减法.此外,只有当两个指向对象是唯一完整对象的子对象时,才能执行两个指针的比较.
这种限制的原因是什么?
我认为分段内存模型(参见这里 §1.2.1)可能是其中一个原因,但由于编译器实际上可以定义所有指针的总顺序,如本答案所示,我对此表示怀疑.
Joh*_*han 11
原因是保持生成合理代码的可能性.这适用于具有平坦内存模型的系统以及具有更复杂内存模型的系统.如果您禁止(不是非常有用的)极端情况,例如添加或减去数组,并要求对象之间的指针的总顺序,您可以跳过生成的代码中的大量开销.
标准施加的限制允许编译器对指针算法进行假设,并使用它来提高代码的质量.它涵盖了在编译器中静态计算事物而不是在运行时,并选择使用哪些指令和寻址模式.作为一个例子,考虑两个指针的程序p1
和p2
.如果编译器可以推导出它们指向不同的数据对象,则可以安全地假设任何基于以下操作的操作p1
都不会影响指向的对象p2
.这允许编译器基于此p1
而不考虑基于的加载和存储p2
以及相反的方式对加载和存储进行重新排序.
Han*_*son 10
你只能证明限制可以被删除 - 但是错过它会带来成本(在内存和代码方面) - 这与C的目标相反.
具体来说,差异需要有一个类型,即ptrdiff_t,并且可以假设它类似于size_t.
在分段存储器模型中,您(通常)间接地限制对象的大小 - 假设答案在:16位的"size_t","uintptr_t","intptr_t"和"ptrdiff_t"类型的实际大小是多少使用分段寻址模式的系统?是正确的.
因此,至少对于删除该限制的差异,不仅会添加额外的指令以确保总顺序 - 对于不重要的角落情况(如在其他答案中),还要花费双倍的内存量来进行差异等.
C被设计为更简约,并且不强迫编译器在这种情况下花费内存和代码.(在那些日子里,记忆限制更重要.)
显然还有其他好处 - 比如混合来自不同阵列的指针时检测错误的可能性.类似地,在C++中没有定义两个不同容器的混合迭代器(有一些小的例外) - 并且一些调试实现检测到这样的错误.
Mar*_*som 10
存在程序和数据空间分离的架构,并且根本不可能减去两个任意指针.指向函数或const静态数据的指针将与正常变量位于完全不同的地址空间中.
即使您在不同的地址空间之间任意提供排名,也有可能该diff_t
类型需要更大的尺寸.并且比较或减去两个指针的过程将非常复杂.在一种专为速度而设计的语言中,这是一个坏主意.
归档时间: |
|
查看次数: |
1195 次 |
最近记录: |