【发布时间】:2014-12-22 18:59:30
【问题描述】:
给定一个指针p:
char *p ; // Could be any type
假设 p 被正确初始化是以下格式:
if (p > 0) // or p > nullptr
更一般地说,当一个操作数是指针而另一个操作数是空指针常量时,使用关系运算符是否格式正确?
【问题讨论】:
标签: c++ pointers c++11 language-lawyer c++14
给定一个指针p:
char *p ; // Could be any type
假设 p 被正确初始化是以下格式:
if (p > 0) // or p > nullptr
更一般地说,当一个操作数是指针而另一个操作数是空指针常量时,使用关系运算符是否格式正确?
【问题讨论】:
标签: c++ pointers c++11 language-lawyer c++14
在 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])需要 每当操作数之一为 指针类型。所以它看起来像“null-ptr-to-real-pointer-type” 转换与其他指针转换搭上了顺风车。
在 C++14 中,当 N3624 为 applied to the draft C++14 standard(N3478 的修订版)时,它的格式不正确。建议的决议583 备注:
此问题已通过问题 1512 的解决方案得到解决。
问题1512建议的解决方案是N3478(N3624 是 N3478 的修订版):
建议的措辞可在文档 N3478 中找到。
第 5.9 节从 C++11 到 C++14 的更改
5.9 部分 关系运算符在 C++11 draft standard 和 C++14 draft standard 之间发生了很大变化,以下突出显示了最相关的差异(强调我的未来) ,来自1段:
操作数应具有算术、枚举或指针类型,或 键入 std::nullptr_t。
更改为:
操作数应具有算术、枚举或指针类型
所以std::nullptr_t 类型不再是有效的操作数,但仍然留下0,它是一个空指针常量,因此可以转换(4.10 部分 em>) 到一个指针类型。
这在 2 段中涵盖,在 C++11 中说:
[...]指针转换 (4.10) 和限定转换 (4.4) 在指针操作数上执行(或在指针操作数和空 指针常量,或在两个空指针常量上,至少一个 这是非整数的)将它们带到它们的复合指针类型。 如果一个操作数是空指针常量,则复合指针类型 如果另一个操作数也是空指针常量,则为 std::nullptr_t 或者,如果另一个操作数是指针,则另一个的类型 操作数。[...]
this 为 空指针常量 操作数显式提供异常,在 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指向不同的对象 不是同一对象的成员或同一数组的元素 或者不同的函数,或者如果其中只有一个为空,则结果 p
q、p=q 的数量未指定。
【讨论】:
char* p = ""; char* q = nullptr; if ( p > q ) {} 还可以?
3 和4 的阅读,我没有从标准草案N3936 中引用,是该比较的结果是未指定的,但自p 和q 都是指针。