int 数字 -> 指针转换规则

use*_*767 19 c++ types visual-c++

考虑以下代码。

void f(double p) {}
void f(double* p) {}

int main()
{ f(1-1); return 0; }
Run Code Online (Sandbox Code Playgroud)

MSVC 2017 不编译。它认为存在一个不明确的重载调用,因为1-1与 相同0,因此可以转换为double*. 其他技巧,如0x00L、 或static_cast<int>(0),也不起作用。即使声明 aconst int Zero = 0并调用也会f(Zero)产生相同的错误。如果Zero不是,它只能正常工作const

看起来同样的问题适用于 GCC 5 及更低版本,但不适用于 GCC 6。我很好奇这是 C++ 标准的一部分、已知的 MSVC 错误还是编译器中的设置。粗略的谷歌没有产生结果。

wal*_*nut 18

MSVC 认为1-1是空指针常量。这对于 C++03 的标准来说是正确的,其中所有具有 value 的整数常量表达式0都是空指针常量,但它已更改,以便只有零整数文字是 C++11 与CWG 问题 903 的空指针常量。这是一个重大更改,正如您在示例中所看到的,并且标准中也有记录,请参阅C++14 标准(草案 N4140)的[diff.cpp03.conv]

MSVC 仅在一致性模式下应用此更改。因此,您的代码将使用该/permissive-标志进行编译,但我认为该更改仅在 MSVC 2019 中实现,请参见此处

在 GCC 的情况下,GCC 5 默认为 C++98 模式,而 GCC 6 及更高版本默认为 C++14 模式,这就是为什么行为变化似乎取决于 GCC 版本的原因。

如果您f使用空指针常量作为参数调用,则调用是不明确的,因为空指针常量可以转换为任何指针类型的空指针值,并且这种转换与int(或任何整数类型)的转换具有相同的等级到double