鉴于p是一个指针是"p> nullptr"格式良好?

Sha*_*our 21 c++ pointers language-lawyer c++11 c++14

给出一个指针p:

char *p ; // Could be any type
Run Code Online (Sandbox Code Playgroud)

假设p正确初始化是以下格式良好:

if (p > 0) // or p > nullptr
Run Code Online (Sandbox Code Playgroud)

更一般地说,当一个操作数是指针而另一个是空指针常量时,使用关系运算符是否良好?

Sha*_*our 27

在C++ 14中,这段代码格式不正确,但在C++ 14之前,这是格式良好的代码(但结果未指定),因为缺陷报告583:与空指针常量的关系指针比较注意:

在C中,这是不正确的(参见C99 6.5.8):

void f(char* s) {
    if (s < 0) { }
}
Run Code Online (Sandbox Code Playgroud)

...但在C++中,它不是.为什么?当他们可以写(s!= 0)时,谁需要写(s> 0)?

这是自ARM以来的语言(可能更早); 显然这是因为只要其中一个操作数是指针类型,就需要在两个操作数上执行指针转换(4.10 [conv.ptr]).因此看起来"null-ptr-to-real-pointer-type"转换正在与其他指针转换搭便车.

在C++ 14将其制成形成不良时N3624施加到草案C++ 14标准,这是的修订版N3478.拟议决议案583注意到:

问题1512的决议解决了这个问题.

1512提出建议的解决方案N3478(N3624是N3478的修订版):

拟议的措辞见N3478号文件.

将5.9节从C++ 11更改为C++ 14

章节5.9 关系运算符C++ 11草案标准C++ 14草案标准之间发生了很大的变化,下面重点介绍了最相关的差异(强调我的未来),来自段落1:

操作数应具有算术,枚举或指针类型,或者类型为std :: nullptr_t.

更改为:

操作数应具有算术,枚举或指针类型

因此类型std :: nullptr_t不再是有效的操作数,但仍然留下0哪个是空指针常量,因此可以转换(4.10)为指针类型.

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 ) {}
Run Code Online (Sandbox Code Playgroud)

是的,在C++ 14这个代码是公形成,两者pq是指针,但比较的结果是不确定的.两个指针的定义比较在段落中列出,3并说:

比较指向对象的指针定义如下:

  • 如果两个指针指向同一数组的不同元素或其子对象,则指向具有较高下标的元素的指针比较大.

  • 如果一个指针指向一个数组的元素或指向其子对象,而另一个指针指向一个超过该数组的最后一个元素的指针,则后一指针比较大.

  • 如果两个指针指向同一对象的不同非静态数据成员,或者指向这些成员的子对象,则递归地指向稍后声明的成员的指针比较更大,前提是两个成员具有相同的访问控制(第11条)并提供它们的上课不是工会.

这里没有定义空指针值,后面的段落中4说明了:

[...]否则,未指定每个运算符的结果.

在C++ 11中,它专门使段落中未指定结果3:

如果同一类型的两个指针p和q指向不是同一个对象的成员或同一个数组的元素或不同函数的不同对象,或者只有其中一个为null,则p <q,p的结果> q,p <= q,p> = q未指定.

  • @JasonC在C++中查看指针比较/等的方法是考虑一个严重分段的内存模型.指针分为高字和低字组成,其中高字是段.这些部分重叠.给定的C++结构必须适合给定的段(事实上它通常不允许到达末尾),这允许许多指针比较仅与低字数据一起发生,通常是高性能增加.null可能是0段0偏移指针,或者可能是-1段-1偏移指针,因为0 0用于硬件中的某些东西! (2认同)