首页 > 解决方案 > 指向不同类型的指针可以有不同的二进制表示吗?

问题描述

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

我问是因为[expr.reinterpret.cast/7]

对象指针可以显式转换为不同类型的对象指针。v对象指针类型的纯右值转换为对象指针类型“指向cv T的指针”时,结果为static_­cast<cv T*>(static_­cast<cv void*>(v)).

[注7:将指向类型T1对象的“pointer to”T1类型的指针转​​换为“pointer to T2”类型(其中T2是对象类型,对齐要求T2不比的更严格T1)并返回其原始type 产生原始指针值。——尾注]

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

标签: c++pointerslanguage-lawyerbit-representation

解决方案


是的

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

void*存储额外的偏移量,但int*不存储。转换int*char*作品(因为它必须根据标准),但char*int*失去该偏移量(您的注释隐含允许)。

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

我会看看我是否能找到标准论点,为什么这对于兼容的 C++ 编译器来说是有效的;我只知道有人这样做,并不是说这样做是合法的,而是该注释暗示它是合法的。

这些规则将在 to-from void 指针转换规则中。您引用的段落隐含地将转换的含义转发到那里。

7.6.1.9 静态转换 [expr.static.cast]

“指向 cv1 void 的指针”类型的纯右值可以转换为“指向 cv2 T 的指针”类型的纯右值,其中 T 是对象类型,而 cv2 与 cv1 具有相同的 cv 限定或大于 cv1 的 cv 限定。如果原始指针值表示内存中一个字节的地址A,并且A不满足T的对齐要求,则结果指针值未指定。否则,如果原始指针值指向对象 a,并且存在与 a 指针可互转换的类型为 T(忽略 cv 限定)的对象 b,则结果是指向 b 的指针。否则,指针值不会因转换而改变。

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

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

然而,每个对象无关的指针转换都需要在逻辑上往返void*

对象指针可以显式转换为不同类型的对象指针。当对象指针类型的纯右值 v 转换为对象指针类型“指向 cv T 的指针”时,结果为static_­cast<cv T*>(static_­cast<cv void*>(v))

(来自OP)

涵盖void*T*; 我还没有找到T*转换void*文本来使它成为一个完整的级别的答案。


推荐阅读