简体   繁体   English

指向不同类型的指针可以有不同的二进制表示吗?

[英]Can pointers to different types have different binary representations?

I wonder if C++ implementations are allowed to represent pointers to different types differently.我想知道是否允许 C++ 实现以不同方式表示指向不同类型的指针。 For instance, if we had 4-byte sized/aligned int and 8-byte sized/aligned long , would it be possible to represent pointers-to- int / long as object addresses shifted right by 2/3 bits, respectively?例如,如果我们有 4 字节大小/对齐的int和 8 字节大小/对齐long ,是否可以将指向int / long的指针分别表示为右移 2/3 位的 object 地址? This would effectively forbid to convert a pointer-to- long into a pointer-to- int .这将有效地禁止将 pointer-to- long转换为 pointer-to- int

I am asking because of [expr.reinterpret.cast/7] :我问是因为[expr.reinterpret.cast/7]

An object pointer can be explicitly converted to an object pointer of a different type. object 指针可以显式转换为不同类型的 object 指针。 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T ”, the result is static_cast<cv T*>(static_cast<cv void*>(v)) .当 object 指针类型的纯右值v转换为 object 指针类型“指向cv T的指针”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))

[ Note 7 : Converting a pointer of type “pointer to T1 ” that points to an object of type T1 to the type “pointer to T2 ” (where T2 is an object type and the alignment requirements of T2 are no stricter than those of T1 ) and back to its original type yields the original pointer value. [注7 :将指向T1类型的object的类型“指向T1的指针”类型的指针转换为“指向T2的指针”类型(其中T2是object类型T2的alignment要求并不比T1的要求严格) 并返回其原始类型产生原始指针值。 end note ] ——尾注]

The first sentence suggests that we can convert pointers to any two object types.第一句话建议我们可以将指针转换为任意两个 object 类型。 However, the empathized text in the (not normative) Note 7 then says that the alignment plays some role here as well.然而,(非规范的)注释 7中的同理心文本然后说 alignment 在这里也发挥了一些作用。 (That's why I came up with that int - long example above.) (这就是为什么我想出了上面那个int - long例子。)

Yep是的

As a concrete example, there is a C++ implementation where pointers to single-byte elements are larger than pointers to multi-byte elements, because the hardware uses word (not byte) addressing.作为具体示例,有一个 C++ 实现,其中指向单字节元素的指针大于指向多字节元素的指针,因为硬件使用字(而非字节)寻址。 To emulate byte pointers, C++ uses a hardware pointer plus an extra byte offset.为了模拟字节指针,C++ 使用了一个硬件指针加上一个额外的字节偏移量。

void* stores that extra offset, but int* does not. void*存储额外的偏移量,但int*不存储。 Converting int* to char* works (as it must under the standard), but char* to int* loses that offset (which your note implicitly permits).int*转换为char*是可行的(因为它必须符合标准),但是char*int*会丢失该偏移量(您的注释隐式允许)。

The Cray T90 supercomputer is an example of such hardware. Cray T90 超级计算机就是此类硬件的一个例子。

I will see if I can find the standards argument why this is valid thing for a compliant C++ compiler to do;我会看看我是否能找到标准论证,为什么这对于兼容的 C++ 编译器来说是有效的; I am only aware someone did it, not that it is legal to do it, but that note rather implies it is intended to be legal.我只知道有人这样做了,但并不是说这样做是合法的,而是暗示它是合法的。

The rules are going to be in the to-from void pointer casting rules.这些规则将在 to-from void 指针转换规则中。 The paragraph you quoted implicitly forwards the meaning of the conversion to there.你引用的段落隐含地将转换的含义转发到那里。

7.6.1.9 Static cast [expr.static.cast] 7.6.1.9 Static 演员表 [expr.static.cast]

A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T”, where T is an object type and cv2 is the same cv-qualification as, or greater cv-qualification than, cv1. “指向 cv1 void 的指针”类型的纯右值可以转换为“指向 cv2 T 的指针”类型的纯右值,其中 T 是 object 类型,并且 cv2 与 cv1 具有相同的 cv 资格,或者比 cv1 更高的 cv 资格。 If the original pointer value represents the address A of a byte in memory and A does not satisfy the alignment requirement of T, then the resulting pointer value is unspecified.如果原始指针值表示memory中某个字节的地址A,A不满足T的alignment要求,则得到的指针值未指定。 Otherwise, if the original pointer value points to an object a, and there is an object b of type T (ignoring cv-qualification) that is pointer-interconvertible with a, the result is a pointer to b.否则,如果原始指针值指向 object a,并且有一个类型为 T(忽略 cv 限定)的 object b 可以与 a 进行指针互换,则结果是指向 b 的指针。 Otherwise, the pointer value is unchanged by the conversion.否则,指针值不会因转换而改变。

This demonstrates that converting to more-aligned types generates an unspecified pointer, but converting to equal-or-less aligned types that aren't actually there does not change the pointer value.这表明转换为对齐程度更高的类型会生成一个未指定的指针,但转换为实际上不存在的相等或更少对齐类型不会更改指针值。

Which is permission to make a cast from a pointer to 4 byte aligned data converted to a pointer to 8 byte aligned data result in garbage.允许从指向 4 字节对齐数据的指针转换为指向 8 字节对齐数据的指针导致垃圾。

Every object unrelated pointer cast needs to logically round-trip through a void* however.但是,每个 object 不相关的指针转换都需要在逻辑上通过void*进行往返。

An object pointer can be explicitly converted to an object pointer of a different type. object 指针可以显式转换为不同类型的 object 指针。 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v)) .当 object 指针类型的纯右值 v 转换为 object 指针类型“指向 cv T 的指针”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))

(From the OP) (来自OP)

That covers void* to T* ;这涵盖了void*T* I have yet to find the T* to void* conversion text to make this a complete level answer.我还没有找到T*void*的转换文本来使它成为一个完整的级别的答案。

The answer is yes.答案是肯定的。 Simply because as the standard does not forbid it, an implementation could decide to have different representations for pointers to different types, or even different possible representations for a same pointer.仅仅因为标准不禁止它,实现可以决定对指向不同类型的指针使用不同的表示,甚至对同一指针使用不同的可能表示。

As most architecture now use flat addressing (meaning that the representation of the pointer is just the address), there are no good reason to do that.由于大多数体系结构现在使用平面寻址(意味着指针的表示只是地址),因此没有充分的理由这样做。 But I can still remember the old segment:offset address representation of the 8086 systems, that used to allow 16 bits systems to process 20 bits addresses (1024k).但我仍然记得 8086 系统的旧段:偏移地址表示,它曾经允许 16 位系统处理 20 位地址(1024k)。 It used a 16 bit segment address (shifted by 4 bits to get a real address), and an offset of 16 bits for far pointers, or only 16 bits (relative to the current segment) for near addresses.它使用 16 位段地址(移动 4 位以获得真实地址),以及用于指针的 16 位偏移量,或用于地址的仅 16 位(相对于当前段)。 In this mode, far pointers had a bunch of possible representations.在这种模式下,远指针有一堆可能的表示。 BTW, far addressing was the default (so what was produced by normal source) in the large and compact mode ( ref ).顺便说一句,在大型和紧凑模式 ( ref ) 中,远寻址是默认设置(因此是由普通源产生的)。

I wonder if C++ implementations are allowed to represent pointers to different types differently.我想知道是否允许 C++ 实现以不同方式表示指向不同类型的指针。 For instance, if we had 4-byte sized/aligned int and 8-byte sized/aligned long , would it be possible to represent pointers-to- int / long as object addresses shifted right by 2/3 bits, respectively?例如,如果我们有 4 字节大小/对齐的int和 8 字节大小/对齐long ,是否可以将指针指向int / long表示为 object 地址分别右移 2/3 位? This would effectively forbid to convert a pointer-to- long into a pointer-to- int .这将有效地禁止将指向long的指针转换为指向int的指针。

I am asking because of [expr.reinterpret.cast/7] :我问是因为[expr.reinterpret.cast/7]

An object pointer can be explicitly converted to an object pointer of a different type. object 指针可以显式转换为不同类型的 object 指针。 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T ”, the result is static_cast<cv T*>(static_cast<cv void*>(v)) .当 object 指针类型的纯右值v转换为 object 指针类型“指向cv T的指针”时,结果为static_cast<cv T*>(static_cast<cv void*>(v))

[ Note 7 : Converting a pointer of type “pointer to T1 ” that points to an object of type T1 to the type “pointer to T2 ” (where T2 is an object type and the alignment requirements of T2 are no stricter than those of T1 ) and back to its original type yields the original pointer value. [ Note 7 : Converting a pointer of type “pointer to T1 ” that points to an object of type T1 to the type “pointer to T2 ” (where T2 is an object type and the alignment requirements of T2 are no stricter than those of T1 ) 并返回其原始类型会产生原始指针值。 end note ] ——尾注]

The first sentence suggests that we can convert pointers to any two object types.第一句暗示我们可以将指针转换为任意两个 object 类型。 However, the empathized text in the (not normative) Note 7 then says that the alignment plays some role here as well.然而,(非规范性)注释 7中的移情文本说 alignment 在这里也发挥了一些作用。 (That's why I came up with that int - long example above.) (这就是为什么我想出了上面那个int - long例子。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM