C++ 为什么C++;11是否包含关于比较空指针的奇数子句?
在检查另一个问题的引用时,我注意到C++11中的一个奇怪的子句,位于[expr.rel]^3: 可以比较指向C++ 为什么C++;11是否包含关于比较空指针的奇数子句?,c++,c++11,pointers,language-lawyer,comparison-operators,C++,C++11,Pointers,Language Lawyer,Comparison Operators,在检查另一个问题的引用时,我注意到C++11中的一个奇怪的子句,位于[expr.rel]^3: 可以比较指向void(指针转换后)的指针,结果定义如下:如果 指针表示相同的地址或都是空指针值,如果运算符为 =和false否则;否则,结果未指定 这似乎意味着,一旦将两个指针强制转换为void*,它们的顺序关系就不再得到保证;例如,这: int foo[] = {1, 2, 3, 4, 5}; void *a = &foo[0]; void *b = &foo[1]; std::co
void
(指针转换后)的指针,结果定义如下:如果
指针表示相同的地址或都是空指针值,如果运算符为
=
和false
否则;否则,结果未指定
这似乎意味着,一旦将两个指针强制转换为void*
,它们的顺序关系就不再得到保证;例如,这:
int foo[] = {1, 2, 3, 4, 5};
void *a = &foo[0];
void *b = &foo[1];
std::cout<<(a < b);
intfoo[]={1,2,3,4,5};
void*a=&foo[0];
void*b=&foo[1];
std::coutTL;医生:
- 在C++98/03中,该子句不存在,标准也没有为
void
指针指定关系运算符(核心问题879,见本文末尾)李>
- C++11中添加了关于比较
void
指针的奇怪子句来解决它,但这反过来又导致了另外两个核心问题583和1512(见下文)李>
- 这些问题的解决要求删除该条款,并替换为C++14标准中的措辞,该措辞允许“正常”
void*
比较
核心问题583:
与空指针常量部分的关系指针比较:8.9[expr.rel]
在C中,这是格式错误的(参见C99 6.5.8):
void f(char*s){
如果(s<0){}
}…但是在C++中,它不是。为什么?当他们可以写(s!=0)时,谁会需要写(s>0)?
这是自ARM(可能更早)以来使用的语言;
显然,这是因为指针转换(7.11[conv.ptr])需要
当其中一个操作数为
指针类型。所以它看起来像“null ptr到实指针类型”
转换是和其他指针转换搭便车
拟议决议(2013年4月):
该问题通过第1512期的决议得以解决
核心问题1512:
指针比较与限定转换部分:8.9[expr.rel]
根据8.9[expr.rel]第2段,描述指针
比较,
指针转换(7.11[conv.ptr])和限定转换
(7.5[conv.qual])对指针操作数(或指针)执行
操作数和空指针常量,或两个空指针常量,
其中至少有一个是非整数的)以将它们带到
复合指针类型。这似乎会导致以下情况
示例格式不正确
bool foo(int** x, const int** y) {
return x < y; // valid ? } because int** cannot be converted to const int**, according to the rules of 7.5 [conv.qual] paragraph 4.
bool-foo(整数**x,常数整数**y){
返回x
这对于指针比较来说似乎太严格了,而且是当前的
实现接受这个例子
拟议决议(2012年11月):
上述问题解决方案的相关摘录见论文:
以下内容还解决了核心问题583
5.9 expr.rel第1至5段的变更:
在本节中,以下语句(C++11中的奇数子句)已被删除:
指向void
(指针转换后)的指针可以进行比较,结果定义如下:如果两个指针表示相同的地址或都是空指针值,如果运算符为=
和false
,则结果为true
;否则,结果将不确定
并且添加了以下语句:
- 如果两个指针指向同一数组的不同元素或其子对象,则指向下标较高的元素的指针比较大李>
- 如果一个指针指向数组的一个元素或其子对象,而另一个指针指向数组最后一个元素的另一个指针,则后一个指针比较大李>
因此,在C++14(n4140)第[expr.rel]/3节的最终工作草案中,上述陈述与决议时的陈述相同
通过挖掘添加这一奇怪条款的原因,我找到了一个更早的问题879:。
该问题的拟议解决方案(2009年7月)导致增加该条款,该条款于2009年10月被表决为WP
这就是它被包含在C++ 11标准中的原因。< /P>它不是奇怪的,C和C++是类型化语言,把整数数组的地址分配给VoIP *不是一个类似的赋值,因此需要一个强制转换。静态_-cast(foo)@splaten:任何数据指针都有到
void*
的隐式转换,因此不需要显式转换,尽管在某些奇怪的体系结构上(想到分段内存),到void*
的转换可能不是普通的位拷贝;尽管如此,我无法想象一种体系结构,其中指向“big,void
pointer”的“常规指针”转换不会保留同一数组元素之间的顺序关系“计算a和b之间的元素数量;如果是阴性的话b@MSalters:我还可以想象a-b
被实现为intc;而((c=rand())+b=a)代码>,但这并不意味着它接近合理。:-)此外,我认为它违反了算法/容器部分中规定的时间复杂性要求;bool b=(void*)和c==(void*)和c
将是假的,这与所有理由都不符。我读对了吗?这解释了为什么它被删除了,但为什么
bool foo(int** x, const int** y) {
return x < y; // valid ? } because int** cannot be converted to const int**, according to the rules of 7.5 [conv.qual] paragraph 4.