整数->指针转换规则


19

考虑下面的代码。

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

int main()
{ f(1-1); return 0; }

MSVC 2017不会对此进行编译。它表明存在一个模棱两可的重载调用,因为1-1它与相同0,因此可以转换为double*。其他技巧,例如0x00Lstatic_cast<int>(0)也不起作用。甚至声明a const int Zero = 0和调用都会f(Zero)产生相同的错误。如果Zero不是,它只能正常工作const

似乎同一问题适用于GCC 5及以下版本,但不适用于GCC6。我很好奇这是否是C ++标准的一部分,已知的MSVC错误或编译器中的设置。粗略的Google并未产生结果。

Answers:


18

MSVC认为1-1是一个空指针常量。这对于C ++ 03的标准是正确的,在C ++ 03中,所有带值的整数常量表达式0均为空指针常量,但已对其进行了更改,以便对于C ++ 发行号为903的 C ++ 11,只有零个整数常量为空指针常量。如您在示例中以及标准中所记录的那样,这是一个重大更改,请参阅C ++ 14标准(草案N4140)的[diff.cpp03.conv]

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

对于GCC,GCC 5默认为C ++ 98模式,而GCC 6和更高版本默认为C ++ 14模式,这就是行为更改似乎取决于GCC版本的原因。

如果f使用空指针常量作为参数进行调用,则该调用将是模棱两可的,因为可以将空指针常量转换为任何指针类型的空指针值,并且此转换与int(或任何整数类型)的转换具有相同的等级。到double


-1

编译器可以根据[over.match][conv],尤其是[conv.fpint]和[conv.ptr]正常工作。

标准转换序列是[...]零或一个浮点整数转换,指针转换。

整数类型或无作用域枚举类型的prvalue可以转换为浮点类型的prvalue。如果可能,结果是准确的[等等]

空指针常量是值为零或[...]的整数文字。空指针常量可以转换为指针类型。结果是该类型的空指针值[blah blah]

现在,重载解决方案是在所有候选函数中选择最佳匹配项(作为一项有趣的功能,甚至不需要在调用位置进行访问!)。最佳匹配是具有精确参数的匹配,或者是可能的最少转换。可能会发生零或一标准转换(...每个参数...),并且零比“好”。

(1-1)是带有value的整数文字0

您可以将零整数文字转换为或(或)的一个,只需进行一次转换即可。因此,假设声明了多个这些函数中的一个(如示例中的情况),则存在多个候选者,并且所有候选者都同样好,因此不存在最佳匹配。这是模棱两可的,编译器对抱怨是正确的。doubledouble*nullptr_t


1
如何是1-1一个整数文字?它是一个包含两个带值的整数文字1和一个-运算符的表达式。
胡桃木

@walnut:您可能会提到措辞不便的“二进制数字,八进制数字,数字或十六进制数字的序列”。这是一个非常“不幸”的措词,它暗示了并非如此(即不包括减号)。仅使用“数字”,并且根据“数字”的定义(0 ... 9中的一个),在学步上不可能有任何否定文字(例如-1)。但是,由于默认类型为signed,所以显然有必要这样做,并且也有可能(并且被普遍接受)。
达蒙(Damon)

1
我指的是标准链接中显示的整数字面量的语法,该语法不匹配1-1。C ++没有负整数文字。-1是由1整数文字(带符号类型)和一-元减运算符组成的表达式。另请参见cppreference.com上的“注释”部分。
胡桃木

语法没有它是正确的,但这是无关紧要的。根据需要和定义,C ++ 确实具有否定的文字,因为除非您明确附加u,否则您的文字将按照定义进行签名。带符号的类型确实具有负值(大约50%的可能值为负)。不幸的是,语法(由于我不知道的原因)会以这种方式引起误解,尽管从技术上(根据语法),-1在形式上是肯定的,但从其他所有方面来看都是否定的文字。3 + 4很像是一个文字。
达蒙

顺便说一句-我试过了0U。同样的问题。我没有尝试的是一种enum价值。也许一个有名字的人会改变一切。我最终用decltype和写了一个长表达式remove_reference
user1334767
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.