当我们执行以下操作时会发生什么: 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;
这里适用的规则是什么?
答案 0 :(得分:5)
指针和整数类型之间的所有转换都是 实施定义。标准的唯一保证 就是这样:
可以明确表示整数类型或枚举类型的值 转换为指针。指针转换为整数 足够的大小(如果在实现上存在任何此类)和 返回相同的指针类型将具有其原始值
然而,标准确实发表了声明(in 一个非规范的说明):
对于那些知道这一点的人来说,这并不奇怪 寻址底层机器的结构。
从实施质量的角度来看,如果机器
具有线性寻址,将int
转换为指针应该
得到的值与int
的值相对应,如果
这个词(无论其大小)被视为一个整体类型;在
换句话说,位模式没有改变。如果积分
类型较小,而且是否定的,这是一个悬而未决的问题
它应该是符号扩展,或者是否应该是剩余的位
设置为0.我更喜欢第二个,但我认为两者都可以
被认为&#34;并不令人惊讶&#34;。
从务实的角度来看:有大量的
那里的软件偶尔会投小
void*
的非负整数值,并期望得到它
以后回来演员。正式地说,需要它
首先转换为intptr_t
(或更大);否则代码
不应该编译。但我无法想象编译器会破坏它
除此以外。另一方面,对于负值,我感觉到
显然不太确定。而且我不确定它有多小,
无论是。 (我目前在一个特殊情况下使用该技术
值小于40或50.我使用MSC,g ++和Sun.
CC,至少,我无法想象它在任何其他方面都失败了
我过去使用的主流Unix机器。但我不会
依靠16位英特尔,或其他一些更具异国情调的东西
我见过的机器,当然不是在嵌入式系统上。)
最后,至于你的确切问题:它可能会有所不同。我试试看 并且看,依靠这样做的事实,那就是它 某些代码在某个地方依赖于它做到这一点,并且那个 供应商不会有改变行为的风险。正式,因为它 实现定义后,实现者需要进行文档化 它(当然可以在下一个版本中更改它),但是 我一般都发现非常非常难以找到这个 文档。
编辑:
我刚刚注意到您的最后一个问题涉及unsigned long
long
到int
。这是一个完整的转换,而不是
reinterpret_cast
,因此适用不同的规则。或者更确切地说,
规则在不同的部分中指定:基本规则是
仍然&#34;实施定义&#34;:
如果目标类型已签名,则该值将保持不变 可以在目标类型(和位字段)中表示 宽度);否则,该值是实现定义的。
C标准在这里有所不同,因为它明确地说明了 允许引发实现定义的信号。 (它&#39; S 伸展它有点说&#34;值&#34;在C ++中 标准可能是提高信号,即使这样 首选实施。)在实践中:所有的 我知道编译器只是忽略超高位。
答案 1 :(得分:-1)
行为未定义。什么都可能发生。它甚至不能保证结果是一致的。 reinterpret_cast<void*>(1) == reinterpret_cast<void*>(1)
可能是false
。