Lan*_*yer -1 c++ byte endianness language-lawyer reinterpret-cast
让我们看看以下代码:
int i = 10;
char c = reinterpret_cast<char&>(i);
Run Code Online (Sandbox Code Playgroud)
如果可以使用reinterpret_cast将"指向T1的指针"类型的表达式显式转换为"指向T2的指针"类型,则可以将类型T1的glvalue表达式强制转换为"对T2的引用".结果引用与源glvalue相同的对象,但具有指定的类型.
所以reinterpret_cast<char&>(i)具有指定char类型的左值引用该int对象i.
要进行初始化c,我们需要值,因此应用左值到右值的转换[conv.lval] /3.4:
glvalue指示的对象中包含的值是prvalue结果.
L2R转换的结果是i对象中包含的值.只要值i在char([expr]/4表示否则这是UB)可表示的范围内,变量c应初始化为具有相同的值.
从实现POV开始,在little-endian平台上,通过读取i对象地址处的字节可以轻松实现.但是,在big-endian平台上,编译器必须添加一个偏移量来获取最低有效字节.或者,将整个int对象读入寄存器并屏蔽第一个字节,这对两个端点都是可接受的方法.
如果您认为编译器可以轻松处理上面的代码以生成符合C++ 17标准所要求的代码,那么可以考虑将指针int指向指向i的指针char.这样的转换不会改变指针值,即它仍然指向int对象i,这意味着将间接运算符应用于具有以下L2R转换的指针应该如上所述,即int如果是,则获取对象的值按char类型表示.
在以下代码中
int i = 10;
f(reinterpret_cast<char*>(&i)); // void f(char*)
Run Code Online (Sandbox Code Playgroud)
如果编译器i不知道函数f将对其参数做什么,那么编译器是否应该调整某个偏移的地址?并且编译器也不知道将传递给函数的内容f.上面的代码和函数f在不同的翻译单元中.
例如,如果f取消引用指针以通过它读取值,它将获得该值,i如上所述.但它也可以用指向真实char对象的指针调用,因此f无法调整给定的指针.这意味着调用者应调整指针.但是,如果[basic.types]/3允许,f将指针memcpy复制sizeof(int)到这个大小的字符数组并返回另一个int对象会怎样?很难想象如何在这里调整指针来加工所需的(通过[basic.types]/3和[conv.lval] /3.4)行为.
那么,如果现有的实现真的符合C++ 17标准,那么现有的实现是做什么的?
编辑:完全重写:你已经说服我标准被打破了.
...结果引用与源glvalue相同的对象,但具有指定的类型.
glvalue指示的对象中包含的值是prvalue结果.
我同意字面解释可能会导致您做出的结论.
鉴于您的解释,reinterpret_cast(以及根据其定义的任何内容reinterpret_cast)变得毫无用处,并且不仅在BE系统上,而且在LE系统上也不可能实现(考虑非整数类型之间的重新解释char).因此,我不相信是预期的意思.这可以被视为缺陷报告的候选者.
混淆可能是由于表达式"包含在"中的值,"指示的对象"和"结果指向同一对象"的定义不够准确.澄清或重写部分或全部这些可能是有序的.
[intro.object]/1表示对于非多态对象,"其中发现的值的解释取决于用于访问它们的表达式类型(Clause [expr])."
(重点是标准本身,而不是我的标准)
正如您所注意到的,在您的情况下,此类表达式的类型是char,因此编译器不需要将此值解释为某个对象类型的值int.