在C ++,g ++ / clang ++和vc ++中打印函数的地址,谁是对的? [英] Print an address of function in C++, g++/clang++ vs vc++ , who is right?

查看:295
本文介绍了在C ++,g ++ / clang ++和vc ++中打印函数的地址,谁是对的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下简单程序:

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

它可以在 VC ++ ,但 g ++ & clang ++ 会给出编译错误。

It compiles fine on VC++ but g++ & clang++ gives compilation errors.

请参阅实时演示此处 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);
                                  ^

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

So, the question is which compiler is right here according to C++ standard ? I think behaviour of g++ & clang++ is correct here. I know that I should use reinterpret_cast here instead of static_cast. Is this bug in VC++ compiler ? If answer depends on the specific standard of C++ then also I am curious to know about it.

推荐答案

GCC和Clang是正确的,因为您尝试执行的转换不在 static_cast 可以执行的转换之中。这些转换在[expr.static.cast]中进行了枚举。我将通过引用本节中的段落来简要地总结它们:

GCC and Clang are correct, because the conversion you are attempting to perform is not among those that can be performed by static_cast. Those conversions are enumerated in [expr.static.cast]. I will briefly summarize them with references to paragraphs in that section:


  • 从基数到派生引用转换(p2)

  • 转换为引用兼容类型的xvalue(p3)

  • 使用操作数进行直接初始化的转换(p4)

  • 转换为void(p6)

  • 标准转换顺序的倒数(p7)

  • 整数/枚举转换(p9,p10)

  • 基础到派生指针转换(p11)

  • 派生到基础指针到成员的转换(p12)

  • 指向对象的无效指针指针转换(p13)

  • Base to derived reference conversion (p2)
  • Conversion to xvalue of reference-compatible type (p3)
  • Conversion using the operand for direct-initialization (p4)
  • Conversion to void (p6)
  • Inverse of standard conversion sequence (p7)
  • Integer/enum conversions (p9, p10)
  • Base to derived pointer conversion (p11)
  • Derived to base pointer-to-member conversion (p12)
  • Void pointer to object pointer conversion (p13)

此外,p5表示:


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

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

The conversion of a function or function pointer to void* is not among the conversions listed.

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

In particular, direct-initialization does not apply since there is no standard conversion from function pointer to void*. According to [conv.ptr]/2:


类型为指向 cv <$ c的指针的prvalue $ c> T ,其中 T 是对象类型,可以转换为指针
cv void 。将对象类型的指针的非空指针值转换为指向
cv void 的指针的结果内存中与原始指针值相同的字节的地址。空指针
的值将转换为目标类型的空指针值。

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.

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

Note that this only covers object pointers, not function pointers.

这篇关于在C ++,g ++ / clang ++和vc ++中打印函数的地址,谁是对的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆