指针和不同大小的整数类型之间的reinterpret_cast

时间:2014-07-03 10:39:58

标签: c++ casting implicit-conversion

当我们执行以下操作时会发生什么: 1)

int i = -1; // 32 bit
void *p;
p = reinterpret_cast<void*>(i) 

在64位架构上,sizeof(void *)== 8

2)

long long i; // 64 bit
void *p = (unsigned int)(-1);
i = retinterpret_cast<long long>(p) 

在32位架构sizeof(void *)= 4

我通常理解结果会是什么,但我希望有人能够根据C ++标准来描述机制,以便更好地理解。

在第二种情况下,行为类似于&#34;整体促销&#34;(4.5)(我将为-1)中描述的行为 对于案例&#34; int - unsigned long&#34;,我们通常会说指针转换为有符号整数吗?

3)

int i = ...;
unsigned long long L = ...;
i = L;

这里适用的规则是什么?

2 个答案:

答案 0 :(得分:5)

指针和整数类型之间的所有转换都是 实施定义。标准的唯一保证 就是这样:

  

可以明确表示整数类型或枚举类型的值   转换为指针。指针转换为整数   足够的大小(如果在实现上存在任何此类)和   返回相同的指针类型将具有其原始值

然而,标准确实发表了声明(in 一个非规范的说明):

  

对于那些知道这一点的人来说,这并不奇怪   寻址底层机器的结构。

从实施质量的角度来看,如果机器 具有线性寻址,将int转换为指针应该 得到的值与int的值相对应,如果 这个词(无论其大小)被视为一个整体类型;在 换句话说,位模式没有改变。如果积分 类型较小,而且是否定的,这是一个悬而未决的问题 它应该是符号扩展,或者是否应该是剩余的位 设置为0.我更喜欢第二个,但我认为两者都可以 被认为&#34;并不令人惊讶&#34;。

从务实的角度来看:有大量的 那里的软件偶尔会投小 void*的非负整数值,并期望得到它 以后回来演员。正式地说,需要它 首先转换为intptr_t(或更大);否则代码 不应该编译。但我无法想象编译器会破坏它 除此以外。另一方面,对于负值,我感觉到 显然不太确定。而且我不确定它有多小, 无论是。 (我目前在一个特殊情况下使用该技术 值小于40或50.我使用MSC,g ++和Sun. CC,至少,我无法想象它在任何其他方面都失败了 我过去使用的主流Unix机器。但我不会 依靠16位英特尔,或其他一些更具异国情调的东西 我见过的机器,当然不是在嵌入式系统上。)

最后,至于你的确切问题:它可能会有所不同。我试试看 并且看,依靠这样做的事实,那就是它 某些代码在某个地方依赖于它做到这一点,并且那个 供应商不会有改变行为的风险。正式,因为它 实现定义后,实现者需要进行文档化 它(当然可以在下一个版本中更改它),但是 我一般都发现非常非常难以找到这个 文档。

编辑:

我刚刚注意到您的最后一个问题涉及unsigned long longint。这是一个完整的转换,而不是 reinterpret_cast,因此适用不同的规则。或者更确切地说, 规则在不同的部分中指定:基本规则是 仍然&#34;实施定义&#34;:

  

如果目标类型已签名,则该值将保持不变   可以在目标类型(和位字段)中表示   宽度);否则,该值是实现定义的。

C标准在这里有所不同,因为它明确地说明了 允许引发实现定义的信号。 (它&#39; S 伸展它有点说&#34;值&#34;在C ++中 标准可能是提高信号,即使这样 首选实施。)在实践中:所有的 我知道编译器只是忽略超高位。

答案 1 :(得分:-1)

行为未定义。什么都可能发生。它甚至不能保证结果是一致的。 reinterpret_cast<void*>(1) == reinterpret_cast<void*>(1)可能是false