2017-04-20 99 views
1

考虑下面的程序:在C++中打印函数地址,g ++/clang ++ vs vC++,谁对?

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

它编译罚款VC++g++ & clang++给出编译错误。

见现场演示hereVC++

见现场演示hereclang++

见现场演示通过g++ & clang++给出hereg++

诊断:

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++编译器中有这个bug吗?如果答案取决于C++的具体标准,那么我也很想知道它。

+0

foo衰变成函数指针!!! – Destructor

+0

如果你想要MSVC的正确性,请确保使用最近添加的'/ permissive-'MSVC14.1。这也更一般地提到MSVC,而不是VC++。 – tambre

回答

9

GCC和Clang是正确的,因为您尝试执行的转换不在static_cast可执行的转换中。这些转换枚举在[expr.static.cast]中。

  • 基地衍生引用转换(P2)
  • 转换到参考兼容型(P3)使用操作数用于直接
  • 转换的x值:我将简要地与在该部分段落的引用总结它们-initialization(P4)
  • 转换为void(P6)
  • 逆标准转换序列(P7)
  • 整数/枚举转换(P9,P10)的
  • 基地衍生指针转换(P11)
  • 衍生于碱指针到构件转换(P12)
  • void指针为一个对象指针转换(P13)

此外,P5表示:

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

函数或函数指针转换为void*不在列出的转换之列。

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

类型的prvalue“指针CVT”,其中T是对象类型,可被转化为式指针 ”一prvalue到CVvoid“。将指针的非空指针值转换为对象类型为“指向 cvvoid”的结果表示与原始指针值相同的字节在存储器中的地址。将空指针 的值转换为目标类型的空指针值。

请注意,这只包括对象指针,而不是函数指针。

1

this pointers-to-void reference:任何类型的

指针对象可以隐式转换到指针void

[着重矿]

而且from this function reference

函数不是对象

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

+0

这并不回答哪个编译器是正确的问题。所以,如果你拿出标准的引用,会更好! – Destructor

+0

@Destructor更新了答案 –