用C++打印函数地址,g ++/clang ++ vs vc ++,谁是对的?

Des*_*tor 1 c++ static-cast visual-c++ reinterpret-cast clang++

考虑以下简单程序:

#include <iostream>
void foo() { }
int main() {
    std::cout<<static_cast<void*>(foo);
}
Run Code Online (Sandbox Code Playgroud)

它编译罚款VC++,但g++clang++给编译错误.

在这里看现场演示(VC++)

在这里看现场演示(clang++)

在这里看现场演示(g++)

诊断由g++&给出clang++:

source_file.cpp: In function ‘int main()’:
source_file.cpp:4:38: error: invalid static_cast from type ‘void()’ to type ‘void*’
     std::cout<<static_cast<void*>(foo);
                                  ^
Run Code Online (Sandbox Code Playgroud)

那么,问题是根据C++标准,哪个编译器就在这里?我认为,行为g++clang++正确这里.我知道我应该reinterpret_cast在这里使用而不是static_cast.这是VC++编译器中的错误吗?如果答案取决于C++的具体标准,那么我也很想知道它.

Bri*_*ian 9

GCC和Clang是正确的,因为您尝试执行的转换不属于可以执行的转换static_cast.这些转换在[expr.static.cast]中枚举.我将简要总结一下这一段中的段落:

  • 基于派生参考转换(p2)
  • 转换为参考兼容类型的xvalue(p3)
  • 使用操作数进行直接初始化转换(p4)
  • 转换为无效(p6)
  • 反转标准转换序列(p7)
  • 整数/枚举转换(p9,p10)
  • 基于派生指针转换(p11)
  • 派生到指针到成员的转换(p12)
  • Void指向对象指针转换的指针(p13)

此外,p5说:

不得使用a明确执行其他转换static_cast.

函数或函数指针void*的转换不在列出的转换中.

特别是,直接初始化不适用,因为没有从函数指针到标准的转换void*.根据[conv.ptr]/2:

类型为"指向cv的 指针"的prvalue T,其中T是对象类型,可以转换为类型为"指向cv的 指针"的prvalue void.将指针的非空指针值转换为对象类型的结果为"指向cv的 指针 void"表示存储器中与原始指针值相同的字节的地址.空指针值将转换为目标类型的空指针值.

请注意,这仅涵盖对象指针,而不是函数指针.