首页 > 解决方案 > 使用 reinterpret_cast 通过引用传递值

问题描述

#include <iostream>

void inc(long& in){
 in++;
}

int main(){
 int a = 5;
 inc(*reinterpret_cast<long*>(&a));

 printf("%d\n", a);
 return 0;
}

上面的代码编译成功并打印6。是undefined behaviour吗?因为我并没有真正引用堆栈上的任何内容。我正在做一个内联演员。

请注意,这不适用于正常的强制转换,例如static_cast<long>(a),您将收到编译器错误消息:

candidate function not viable: expects an l-value for 1st argument

为什么要*reinterpret_cast<long*>(&a)编译?我将它取消引用到 along所以编译器应该能够告诉它没有引用任何东西。

编辑

请忽略int/long这里的区别,这不是我问题的重点。假设这个例子更有意义:

void inc(int& in){...}
...
inc(*reinterpret_cast<int*>(&a));

我的问题是,如何*reinterpret_cast<int*>(&a)作为参考传递但static_cast<int>(a)不是?

标签: c++

解决方案


它是未定义的行为吗?

是的。

为什么要*reinterpret_cast<long*>(&a)编译?

因为它的格式很好。通过使用reinterpret_cast,您是在告诉编译器您知道自己在做什么,并且它将是正确的。编译器别无选择,只能相信你。问题是它不正确而且你不知道。

如果地址实际上包含一个类型的对象,那就没问题了long。例如,以下将具有明确定义的行为(因为标准布局类及其第一个成员是指针可互转换的):

struct T {
    long l;
} a {42};

// no problem
inc(*reinterpret_cast<long*>(&a));

允许这种重新解释的另一种情况是窄字符类型和std::byte. 在实践中它可能从未与参考一起使用,但这在技术上是可以的:

void inc(std::byte&);
int a = 42;
// you will get the first byte
inc(*reinterpret_cast<std::byte*>(&a));

推荐阅读