给出以下功能:
void g(int **p1, const int**p2)
{
if (p1 == p2) { }
}
clang
(返回3.0版)会产生此警告( see it live ):
warning: comparison of distinct pointer types ('int **' and 'const int **')
uses non-standard composite pointer type 'const int *const *'
[-Wcompare-distinct-pointer-types]
if (p1 == p2) { }
~~ ^ ~~
使用-pedantic-errors
标志会将其变为错误。根据标准,gcc
(回4.3.6 )和Visual Studio
( 2013 )都不会产生警告,是比较:< / p>
p1 == p2
结构良好?
更一般地说,如果两个多级指针的 cv-qualifications 不同于第一级,那么通过等式运算符或关系运算符进行比较是否很好?
答案 0 :(得分:24)
在C ++ 14之前,这个案例是形成错误的,一些例外的更一般的案例也是不正确的。这在defect report 1512: Pointer comparison vs qualification conversions 中有所说明,其中包含:
根据5.9 [expr.rel]第2段,描述指针 比较,
指针操作数(或更高版本)执行指针转换(4.10 [conv.ptr])和限定转换(4.4 [conv.qual]) 指针操作数和空指针常量,或两个空指针 将它们带到的常数,其中至少有一个是非整数的 他们的复合指针类型。
这似乎使以下示例格式错误,
bool foo(int** x, const int** y) { return x < y; // valid ? }
因为int **不能转换为const int **,根据 4.4 [conv.qual]第4段的规则。这似乎过于严格 指针比较,当前的实现接受了这个例子。
缺陷报告指出虽然这是不正确的,但实施方案接受了这种比较。这个clang commit表示它被视为一个扩展名,表示gcc
和EDG
也将此视为扩展,可能是Visual Studio的情况。
标准由N3624: Core Issue 1512: Pointer comparison vs qualification conversions解决,其中说:
本文介绍了必要的工作草案修改 解决核心问题583和1512.特别是,它使
[...]
和
void g(int **p1, const int**p2) { if (p1 == p2) { ... } }
良好的。
同时请注意,在meeting it was accepted中,有人指出这只是编纂了现有做法。
在标准的其他更改中,此段落已添加到5
[expr] 部分的末尾,其中包含新术语 cv-combined type :
两种类型T1和T2的cv组合类型是类似于T1的类型T3 其cv资格签名(4.4)是:
- 对于每个j&gt; 0,cv3,j是cv1,j和cv2,j;
的并集- 如果得到的cv3,j不同于cv1,j或cv2,j,则将const添加到每个cv3,k为0 <0。 k&lt;学家
[注:给出类似的T1类型 和T2,这种结构确保两者都可以转换为T3。 -end note]两个操作数p1和p2的复合指针类型 分别具有类型T1和T2,其中至少一个是指针 或指向成员类型或std :: nullptr_t的指针是:
- 如果p1和p2都是空指针常量,则为std :: nullptr_t;
- 如果p1或p2分别是空指针常量,T2或T1;
- 如果T1或T2是“指向cv1 void的指针”而另一种类型是“指向cv2 T的指针”,“指向cv12 void的指针”,其中cv12是cv1的并集 cv2;
- 如果T1是“指向cv1 C1的指针”而T2是“指向cv2 C2的指针”,其中C1是与C2相关的参考或C2是与C1相关的引用(8.5.3), cv-组合型T1和T2或cv-组合型T2和 分别为T1;
- 如果T1是“指向cv1 U1类型C1的成员的指针”,T2是“指向cv2 U2类型C2的成员的指针”,其中C1是与C2相关的参考或 C2与参考相关的C1(8.5.3),cv组合类型的T2和 分别为T1或cv组合型T1和T2;
- 如果T1和T2是类似的多级混合指针和指向成员类型的指针(4.4),则是cv-combined类型的T1和T2;
- 否则,需要确定复合指针类型的程序是不正确的。
[例如:
typedef void *p; typedef const int *q; typedef int **pi; typedef const int **pci;
p和q的复合指针类型是“指向const void的指针”;该 pi和pci的复合指针类型是“指向const指针的指针 const int“。 - 例子]