【发布时间】:2019-06-19 02:34:34
【问题描述】:
在检查另一个问题的参考资料时,我注意到 C++11 中有一个奇怪的子句,位于 [expr.rel] ¶3:
可以比较指向
void(指针转换后)的指针,结果定义如下:如果两者 指针表示相同的地址或者都是空指针值,如果运算符是,则结果是true<=或>=和false否则;否则结果未指定。
这似乎意味着,一旦两个指针被强制转换为void *,它们的顺序关系就不再得到保证;例如,这个:
int foo[] = {1, 2, 3, 4, 5};
void *a = &foo[0];
void *b = &foo[1];
std::cout<<(a < b);
似乎未指定。
有趣的是,这个子句在 C++03 中不存在,而在 C++14 中消失了,所以如果我们以上面的例子应用 C++14 的措辞,我会说 ¶3.1
- 如果两个指针指向同一数组的不同元素或其子对象,则指向具有较高下标的元素的指针比较大。
将适用,因为 a 和 b 指向同一数组的元素,即使它们已被强制转换为 void *。请注意,¶3.1 的措辞在 C++11 中几乎相同,但似乎被 void * 子句覆盖。
我的理解是否正确?在 C++11 中添加并立即删除的那个奇怪的子句有什么意义?或者它可能仍然存在,但被标准的其他部分移动/暗示?
【问题讨论】:
-
这并不奇怪,C 和 C++ 是类型化语言,将整数数组的地址分配给 void* 与类似分配不同,因此需要强制转换。 static_cast
(foo); -
@SPlatten:任何数据指针都隐式转换为
void *,因此不需要显式转换,尽管确实在某些奇怪的架构(想到分段内存)上转换为void *可能不是普通的按位复制;尽管如此,我仍然无法想象一个架构,其中“常规指针”到“大,void指针”转换不会保留同一数组的元素之间的排序关系。 -
我可以将图像指针比较实现为“计算 a 和 b 之间的元素数量;如果它是负数,则 bvoid*,因为没有
void[]。 -
@MSalters:我也可以想象
a - b被实现为int c; while((c = rand()) + b == a);,但这并不意味着它几乎是明智的。 :-) 另外,我希望它违反算法/容器部分中某处所述的时间复杂度要求。 -
根据该条款的措辞
char c; bool b = (void *)&c == (void *)&c将是错误的,完全没有理由。我读对了吗?
标签: c++ c++11 pointers language-lawyer comparison-operators