作者:育诚家瑋逸群 | 来源:互联网 | 2022-12-06 16:55
我的心智模型reinterpret_cast
一直是,将表达式的位序列视为不同类型,并且cppreference(注意:这不是C++标准中的引用)似乎同意这一点:
不像static_cast
,但是const_cast
,reinterpret_cast
表达式不会编译到任何CPU指令.它纯粹是一个编译器指令,它指示编译器将表达式的位序列(对象表示)视为具有new_type类型.
寻找保证,我偶然发现[expr.reinterpret.cast]下的一个注释:
[ 注意:由may执行reinterpret_cast
或可能不执行的映射会生成与原始值不同的表示.- 结束说明 ]
这让我想知道:在哪个条件下reinterpret_cast
产生的值与对象表示不同于原始值?
1> geza..:
这是一个例子:如果您阅读第4个要点:
指针可以显式转换为足以容纳其类型的所有值的任何整数类型.映射函数是实现定义的.[注意:对于那些了解底层机器的寻址结构的人来说,这并不奇怪. - 结束说明]
现在,它是实现定义的,i
这里有什么价值:
void *ptr = ;
uintptr_t i = reinterpret_cast(ptr);
它可以是任何东西,只要reinterpret_cast
荷兰国际集团i
前,我们会得到ptr
.
表示ptr
和i
可能不同.标准只是说价值i
应该"不足为奇".甚至,如果我们reinterpret_cast
ptr
使用更宽的整数(例如,如果指针是32位,则转换为unsigned long long int
),则表示必须不同,因为变量的大小不同.
所以我认为cppreference描述是误导性的,因为可能有reinterpret_cast
s,它实际上需要CPU指令.
这是另一个案例(由IInspectable发现),Keith Thompson的评论:
用于Cray向量机的C编译器,例如T90,做类似的事情.硬件地址为8个字节,指向8个字节的字.void*和char*在软件中处理,并在字内增加3位偏移量 - 但由于实际上没有64位地址空间,因此偏移量存储在高位3位64位字.因此char*和int*的大小相同,但具有不同的内部表示 - 并且假定指针"真的"只是整数的代码可能会严重失败.
char *
并且int *
在Cray T90上有不同的表现形式,所以:
int *i = ;
char *c = reinterpret_cast(i);
在这里,i
并且c
将对Cray T90有不同的表示(并且这种转换肯定使用CPU指令).
(我已经验证了这一点,Cray C/C++参考手册SR-2179 2.0的第3.1.2.7.1章)
@NeilButterworth:给定`#include
`/`uint64_t foo(void*x){return reinterpret_cast (x); 用`c ++ -O3 -m32 -S`调用的Apple LLVM 9.1.0(clang-902.0.39.2)生成`movl 8(%ebp),%eax` /`xorl%edx,%edx`,因此服用作为输入一个四字节对象并产生一个八字节对象作为输出.