void* ptr = &func; 使用 msvc 进行编译,无需任何诊断,但 gcc 和 clang 都拒绝它

Ala*_*lan 4 c++ pointers function-pointers language-lawyer pointer-conversion

我正在使用 Stanley 的《C++ Primer》一书学习 C++。特别是,关于“指针转换”的部分说:

指向任何非常量类型的指针都可以转换为void*


读完本文后,我编写了以下程序,该程序使用 msvc 进行编译,没有任何诊断,但被 gcc 和 clang 拒绝。演示

int func()
{
    return 4;
}
int main()
{
    void* ptr = &func; //works with msvc but rejected by clang and gcc
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,上面的程序适用于 msvc,但 gcc 说error: invalid conversion from 'int (*)()' to 'void*'

我想知道哪个编译器在这里是正确的。请注意,我已将/permissive-flag 与 msvc 一起使用以使其符合标准。

use*_*570 5

该程序格式错误,因为没有从指针到“函数类型”到 的隐式转换void*。仅当目标是“对象类型”时才允许隐式转换,但事实int()并非如此。这可以从conv.ptr#2中看出,其中指出:

\n
\n

指向 cv T\xe2\x80\x9d 的 \xe2\x80\x9c 类型的纯右值(其中T是对象类型)可以转换为 \xe2\x80\x9cpointer\n 类型的纯右值到 cv void\xe2\x80\x9d 。此转换不会改变指针值 (6.8.3)

\n
\n

进一步来自dcl.init#general

\n
\n

否则,正在初始化的对象的初始值是初始值设定项表达式的(可能已转换的)值。\n标准转换序列 ([conv]) 用于将初始值设定项表达式转换为 cv 未限定版本的纯右值目的地类型;不考虑用户定义的转换。\n如果无法完成转换,则初始化格式错误。\n当使用无法表示的值初始化位字段时,位字段的结果值是实现定义的。

\n
\n

(强调我的)

\n

请注意“对象类型”一词的强调。而且由于您的代码中T=int()“函数类型”,因此没有从 到 的转换,这int(*)()意味着void*程序格式不正确,并且msvc 在没有任何诊断的情况下接受程序是错误的。

\n