c++ - 指向不同类型的指针可以有不同的二进制表示吗?
问题描述
我想知道是否允许 C++ 实现以不同的方式表示指向不同类型的指针。例如,如果我们有 4-byte sized/alignedint
和 8-byte sized/aligned long
,是否可以将指向 / 的指针表示int
为long
分别右移 2/3 位的对象地址?这将有效地禁止将指向指针的指针转换为指向指针long
的指针int
。
我问是因为[expr.reinterpret.cast/7]:
对象指针可以显式转换为不同类型的对象指针。当
v
对象指针类型的纯右值转换为对象指针类型“指向cvT
的指针”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))
.[注7:将指向类型
T1
对象的“pointer to”T1
类型的指针转换为“pointer toT2
”类型(其中T2
是对象类型,对齐要求T2
不比的更严格T1
)并返回其原始type 产生原始指针值。——尾注]
第一句话表明我们可以将指针转换为任意两种对象类型。然而,(非规范性的)注释 7中的移情文本说,对齐在这里也起到了一定的作用。(这就是我想出这个的原因int
——long
上面的例子。)
解决方案
是的
作为一个具体的例子,有一个 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*
文本来使它成为一个完整的语言律师级别的答案。
推荐阅读
- java - Thymeleaf 中的动态 HTML
- javascript - 无论用户输入是什么,对用户输入生成随机答案的游戏都会生成相同的答案
- javascript - 图像轮播
- actionscript-3 - AS3:如何严格测试实例是否为对象类型?
- python - 尽管使用了正确的路径,但 Lambda 的层没有导入外部库
- c# - AuthorizationPolicy 基于 url 中的共享密钥,无需身份验证或身份
- python - 我怎样才能拥有一个每秒更新一次的实时计时器,以查看我的程序运行了多少?Python
- r - 在同一图中绘制模拟回归线
- angular - 如何解决“订阅”类型缺少“Tab2Page”类型中的以下属性:http、navCtrl
- python - Python不会连接到数据库