Vla*_*nin 4 c++ casting implicit-conversion
当我们执行以下操作时会发生什么:1)
int i = -1; // 32 bit
void *p;
p = reinterpret_cast<void*>(i)
Run Code Online (Sandbox Code Playgroud)
在64位架构上,sizeof(void*)== 8
2)
long long i; // 64 bit
void *p = (unsigned int)(-1);
i = retinterpret_cast<long long>(p)
Run Code Online (Sandbox Code Playgroud)
在32位架构sizeof(void*)= 4
我通常理解结果会是什么,但我希望有人能够根据C++标准来描述机制,以便更好地理解.
在第二种情况下,行为类似于"整数提升"(4.5)(我将为-1)中描述的情况"int - unsigned long",所以我们通常说指针转换为有符号整数?
3)
int i = ...;
unsigned long long L = ...;
i = L;
Run Code Online (Sandbox Code Playgroud)
这里有什么规则?
指针和整数类型之间的所有转换都是实现定义的.标准的唯一保证是:
可以将整数类型或枚举类型的值显式转换为指针.转换为足够大小的整数的指针(如果在实现上存在任何此类)并返回到相同的指针类型将具有其原始值
但是,该标准确实声明(在非规范性说明中):
对于那些了解底层机器的寻址结构的人来说,这并不奇怪.
从实现质量的角度来看,如果机器具有线性寻址,那么如果将单词(无论其大小)视为整数类型,则转换int为指针应该产生与该值相对应的值int; 换句话说,位模式不会改变.如果积分类型较小,并且是负数,那么是否应该对符号进行扩展,或者是否应将其余位设置为0是一个悬而未决的问题.我更喜欢第二个,但我认为两者都可以被认为是"不足为奇" .
从一个实用的角度来看:那里有大量的软件,它们偶尔会抛出一个小的非负积分值void*,并期望稍后再投出.正式地,将它取回需要先转换为intptr_t(或更大); 否则代码不应该编译.但我无法想象编译器会破坏它.另一方面,对于负值,我会感到非常不确定.而且我也不确定它的小小.(我目前在一个特殊情况下使用该技术的值小于40或50.我至少使用MSC,g ++和Sun CC,我无法想象它在任何其他主流Unix机器上都失败了我在过去使用过的.但我不会指望它在16位英特尔,或者我见过的其他一些更奇特的机器上,当然也不会在嵌入式系统上.)
最后,至于你的确切问题:它可能会有所不同.我试着看看,依靠这样一个事实,无论它做什么,都有一些代码在某处依靠它做到这一点,并且供应商不会冒险改变行为.形式上,因为它是实现定义,实现者需要将其记录下来(和可能,当然,在未来的版本,它改变),但我通常会发现它非常,非常难以找到这个文件.
编辑:
我只注意到有关您的最后一个问题unsigned long
long来int.这是一个完整的转换,而不是一个reinterpret_cast,因此适用不同的规则.或者更确切地说,规则在不同的部分中指定:基本规则仍然是"实现定义":
如果目标类型已签名,则如果可以在目标类型(和位字段宽度)中表示该值,则该值不会更改; 否则,该值是实现定义的.
这里的C标准有些不同,因为它明确允许引发实现定义的信号.(它有点夸张地说C++标准中的"值"可能是信号的提升,即使这将是首选实现.)在实践中:我所知道的所有编译器都忽略了额外的高阶位.