指向不同类型的Can指针具有不同的二进制表示形式



我想知道是否允许C++实现以不同的方式表示指向不同类型的指针。例如,如果我们有4字节大小/对齐的int和8字节大小/对准的long,是否可以将指向-int/long的指针表示为分别右移2/3位的对象地址?这将有效地禁止将指向-long的指针转换为指向-int的指针。

我之所以提出这个问题,是因为[expr.relinterpret.cast/7]:

对象指针可以显式转换为不同类型的对象指针当对象指针类型的prvaluev转换为对象指针类型"pointer tocvT"时,结果为static_­cast<cv T*>(static_­cast<cv void*>(v))

[注意7:将指向类型为T1的对象的类型为"pointer toT1"的指针转换为类型为"指针toT2"(其中T2的对象类型,T2的对齐要求不比T1的对齐要求更严格)并返回到其原始类型会产生原始指针值。-结束注释]

第一句话建议我们可以将指针转换为任意两种对象类型。然而,(非规范性的)注释7中的移情文本表示,对齐在这里也起到了一定的作用。(这就是为什么我提出了上面的int-long示例。)

是的

作为一个具体的例子,有一个C++实现,其中指向单字节元素的指针大于指向多字节元素的指示器,因为硬件使用字(而不是字节)寻址。为了模拟字节指针,C++使用硬件指针加上额外的字节偏移量。

void*存储该额外偏移,但int*不存储。将int*转换为char*是可行的(在标准下必须如此),但char*int*会丢失该偏移量(您的注释隐含地允许)。

克雷T90超级计算机就是这种硬件的一个例子。

我会看看我是否能找到标准的论点,为什么这对一个兼容的C++编译器来说是有效的;我只知道有人做了这件事,并不是说这样做是合法的,但那张纸条暗示着这是合法的。

这些规则将位于"到"from void指针强制转换规则中。你引用的这段话隐含地将转换的含义转移到了那里。

7.6.1.9静态铸造[expr.Static.cast]

类型为"pointer to cv1 void"的prvalue可以转换为类型为"pointer to cv2 T"的prvalue,其中T是对象类型,cv2与cv1具有相同的cv资格,或者比cv1具有更大的cv资质。如果原始指针值表示内存中字节的地址A,而A不满足T的对齐要求,则结果指针值未指定。否则,如果原始指针值指向对象a,并且存在类型为T(忽略cv限定)的对象b,该对象的指针可与a互换,则结果是指向b的指针。否则,指针值将因转换而保持不变。

这表明转换为更多对齐的类型会生成未指定的指针,但转换为实际上不存在的相等或更少对齐的类型不会更改指针值。

这是允许从指向4字节对齐数据的指针转换为指向8字节对齐数据指针的强制转换导致垃圾。

然而,每个与对象无关的指针投射都需要在逻辑上往返于void*

对象指针可以显式转换为不同类型的对象指针。当对象指针类型的prvalue v转换为对象指针类型"pointer to cv T"时,结果为static_­cast<cv T*>(static_­cast<cv void*>(v))

(来自OP)

这涵盖了void*T*;我还没有找到T*void*的转换文本,使其成为一个完整的语言律师级别的答案。

答案是肯定的。仅仅因为标准没有禁止它,实现可以决定对不同类型的指针使用不同的表示,甚至对同一指针使用不同可能的表示。

由于大多数体系结构现在都使用平面寻址(意味着指针的表示只是地址),因此没有充分的理由这样做。但我仍然记得旧的部分:8086系统的偏移地址表示,它曾经允许16位系统处理20位地址(1024k)。它使用了一个16位的段地址(偏移4位以获得实际地址),指针的偏移量为16位,或者地址的偏移量仅为16位(相对于当前段)。在这种模式下,远指针有一堆可能的表示。顺便说一句,在大而紧凑模式(ref)中,远寻址是默认的(所以正常源产生的)。

相关内容

  • 没有找到相关文章

最新更新