reinterpret_cast可以更改对象表示吗?

IIn*_*ble 9 c++ language-lawyer

我的心智模型reinterpret_cast一直是,将表达式的位序列视为不同类型,并且cppreference(注意:这不是C++标准中的引用)似乎同意这一点:

不像static_cast,但是const_cast,reinterpret_cast表达式不会编译到任何CPU指令.它纯粹是一个编译器指令,它指示编译器将表达式的位序列(对象表示)视为具有new_type类型.

寻找保证,我偶然发现[expr.reinterpret.cast]下的一个注释:

[  注意:由may执行reinterpret_­cast或可能不执行的映射会生成与原始值不同的表示.-  结束说明  ]

这让我想知道:在哪个条件下reinterpret_cast产生的值与对象表示不同于原始值?

gez*_*eza 9

这是一个例子:如果您阅读第4个要点:

指针可以显式转换为足以容纳其类型的所有值的任何整数类型.映射函数是实现定义的.[注意:对于那些了解底层机器的寻址结构的人来说,这并不奇怪. - 结束说明]

现在,它是实现定义的,i这里有什么价值:

void *ptr = <some valid pointer value>;
uintptr_t i = reinterpret_cast<uintptr_t>(ptr);
Run Code Online (Sandbox Code Playgroud)

它可以是任何东西,只要reinterpret_cast荷兰国际集团i前,我们会得到ptr.

表示ptri可能不同.标准只是说价值i应该"不足为奇".甚至,如果我们reinterpret_cast ptr使用更宽的整数(例如,如果指针是32位,则转换为unsigned long long int),则表示必须不同,因为变量的大小不同.

所以我认为cppreference描述是误导性的,因为可能有reinterpret_casts,它实际上需要CPU指令.


是另一个案例(由IInspectable发现),Keith Thompson的评论:

用于Cray向量机的C编译器,例如T90,做类似的事情.硬件地址为8个字节,指向8个字节的字.void*和char*在软件中处理,并在字内增加3位偏移量 - 但由于实际上没有64位地址空间,因此偏移量存储在高位3位64位字.因此char*和int*的大小相同,但具有不同的内部表示 - 并且假定指针"真的"只是整数的代码可能会严重失败.

char *并且int *在Cray T90上有不同的表现形式,所以:

int *i = <some int pointer value>;
char *c = reinterpret_cast<char *>(i);
Run Code Online (Sandbox Code Playgroud)

在这里,i并且c将对Cray T90有不同的表示(并且这种转换肯定使用CPU指令).

(我已经验证了这一点,Cray C/C++参考手册SR-2179 2.0的第3.1.2.7.1章)

  • @NeilButterworth:给定`#include <stdint>`/`uint64_t foo(void*x){return reinterpret_cast <uint64_t>(x); 用`c ++ -O3 -m32 -S`调用的Apple LLVM 9.1.0(clang-902.0.39.2)生成`movl 8(%ebp),%eax` /`xorl%edx,%edx`,因此服用作为输入一个四字节对象并产生一个八字节对象作为输出. (2认同)