给出指针p
:
char *p ; // Could be any type
假设p
已正确初始化,以下格式良好:
if (p > 0) // or p > nullptr
更一般地说,当一个操作数是指针而另一个是空指针常量时,使用关系运算符是否良好?
答案 0 :(得分:27)
在C ++ 14中,这段代码格式不正确,但在C ++ 14之前,这是格式良好的代码(但结果未指定),如defect report 583: Relational pointer comparisons against the null pointer constant所述:
在C中,这是不正确的(参见C99 6.5.8):
void f(char* s) { if (s < 0) { } }
...但在C ++中,它不是。为什么?谁需要写(s> 0) 什么时候他们也可以写(s!= 0)?
这一直是自ARM以来的语言(可能更早); 显然它是因为指针转换(4.10 [conv.ptr])需要 只要其中一个操作数是,就在两个操作数上执行 指针类型。所以它看起来像&#34; null-ptr-to-real-pointer-type&#34; 转换正在与其他指针转换搭便车。
在C ++ 14中,当N3624为applied to the draft C++14 standard N3478
时,这是583
的修订版。建议的1512
注意事项:
第1512期的决议解决了这个问题。
并且问题N3478
建议的解决方案是5.9
( N3624是N3478的修订版):
拟议的措辞见N3478号文件。
第5.9节从C ++ 11更改为C ++ 14
部分1
关系运算符在C++11 draft standard和C++14 draft standard之间发生了很大变化,以下重点介绍了最相关的差异(强调我的进展转发),来自0
段:
操作数应具有算术,枚举或指针类型,或 输入std :: nullptr_t 。
更改为:
操作数应具有算术,枚举或指针类型
因此类型std::nullptr_t不再是有效的操作数,但仍然留下4.10
这是空指针常量,因此可以转换( section { {1}} )到指针类型。
这由第2
段涵盖,在C ++ 11中说:
[...] 指针转换(4.10)和资格转换(4.4) 在指针操作数(或指针操作数和空值上)执行 指针常量,或两个空指针常量,至少有一个 这是非整数)将它们带到复合指针类型。 如果一个操作数是空指针常量,则为复合指针类型 如果另一个操作数也是空指针常量,则为std :: nullptr_t 或者,如果另一个操作数是指针,则另一个操作数的类型 操作数。[...]
这明确地为空指针常量操作数提供了一个例外,在C ++ 14中更改为以下内容:
通常的算术转换是在操作数上执行的 算术或枚举类型。 如果两个操作数都是指针,则指针 执行转换(4.10)和资格转换(4.4) 将它们带到复合指针类型(第5条)。的后 转换时,操作数应具有相同的类型。
其中没有允许0
转换为指针类型的情况。两个操作数必须是指针才能应用指针转换,并且要求转换后操作数具有相同的类型。在一个操作数是指针类型而另一个是空指针常量 0
的情况下不满足。
如果两个操作数都是指针但是一个是空指针值怎么办?
R Sahu问,下面的代码是否格式正确?:char* p = "";
char* q = nullptr;
if ( p > q ) {}
是的,在C ++ 14中,此代码格式正确,p
和q
都是指针,但未指定比较结果。两个指针的定义比较在第3
段中列出,并说:
比较指向对象的指针定义如下:
如果两个指针指向同一个数组或其子对象的不同元素,则指向具有更高元素的元素 下标比较大。
如果一个指针指向一个数组的元素,或指向一个子对象,另一个指针指向一个指针的最后一个元素。 数组,后一个指针比较大。
如果两个指针指向同一个对象的不同非静态数据成员,或者指向这些成员的子对象,则递归地, 指向后来声明的成员的指针比较大,提供了两个 成员具有相同的访问控制(第11条)并提供了他们的 上课不是工会。
此处未定义空指针值,稍后在段落4
中定义:
[...]否则,未指定每个运算符的结果。
在C ++ 11中,它专门在第3
段中未指明结果:
如果同一类型的两个指针p和q指向不同的对象 不是同一对象的成员或同一数组的元素 或者对于不同的函数,或者如果只有其中一个为null,则为结果 p
q,p <= q,p> = q未指定。