c++ - 在 C++ 中打印函数地址,g++/clang++ vs vc++,谁是对的?

标签 c++ visual-c++ clang++ reinterpret-cast static-cast

考虑以下简单程序:

#include <iostream>
void foo() { }
int main() {
    std::cout<<static_cast<void*>(foo);
}

它在 VC++ 上编译良好,但 g++clang++ 给出编译错误。

查看现场演示 here ( VC++ )

查看现场演示 here ( clang++ )

查看现场演示 here ( 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);
                                  ^

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

最佳答案

GCC 和 Clang 是正确的,因为您尝试执行的转换不属于 static_cast 可以执行的转换。 [expr.static.cast] 中列举了这些转换。我将引用该部分中的段落简要总结它们:

  • 基础到派生引用的转换 (p2)
  • 转换为引用兼容类型的 xvalue (p3)
  • 使用直接初始化操作数的转换(p4)
  • 转换为无效 (p6)
  • 标准转换序列的逆(p7)
  • 整数/枚举转换(p9、p10)
  • 从基到派生指针的转换(p11)
  • 派生到基指针到成员的转换(第 12 页)
  • 空指针到对象指针的转换(p13)

此外,p5 说:

No other conversion shall be performed explicitly using a static_cast.

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

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

A prvalue of type “pointer to cv T,” where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The result of converting a non-null pointer value of a pointer to object type to a “pointer to cv void” represents the address of the same byte in memory as the original pointer value. The null pointer value is converted to the null pointer value of the destination type.

请注意,这仅涵盖对象指针,不涵盖函数指针。

关于c++ - 在 C++ 中打印函数地址,g++/clang++ vs vc++,谁是对的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43511868/

相关文章:

c++ - 如何调试 armv5 上的堆损坏

c++ - 知道用户是否选择了子菜单项 MFC

c++ - 函数模板作为成员 - GCC 与 CLANG

c++11 - GCC、Clang 和 MSVC 中的可变参数模板-模板参数和 sizeof 差异 - 谁是对的?

c++ - 尝试在 Linux 上使用 Clang++ 编译 c++11 正则表达式教程时出错

c# - 简单的正则表达式不匹配

c++ - 基于 C++ 中的多个事物进行排序

visual-c++ - 如何关闭 MSVC 中的异常处理?

c++ - 在 C++ 中返回一个数组

c++ - 无法在 VC++ 中从 NASM 调用 c 函数,除了 main,出现链接错误