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

Print an address of function in C++, g++/clang++ vs vc++ , who is right?

考虑以下简单程序:

#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++ 的特定标准,那么我也很想知道它。

来自this pointers-to-void reference

Pointer to object of any type can be implicitly converted to pointer to void

[强调我的]

from this function reference

Functions are not objects

这似乎表明指向函数的指针根本无法转换为void*

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

  • 基础到派生参考的转换 (p2)
  • 转换为引用兼容类型的 xvalue (p3)
  • 使用直接初始化操作数的转换 (p4)
  • 转换为无效 (p6)
  • 标准转换序列的倒数 (p7)
  • Integer/enum 次转化(第 9 页、第 10 页)
  • 从基到派生指针的转换 (p11)
  • 派生到基本指针到成员的转换 (p12)
  • 空指针到对象指针转换 (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.

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