“&a+1 > &a”会导致未定义的行为吗?

17

“c99/c++03”是否保证“&a+1 > &a”始终为真?

例如,有一个(类C语言的)std::copy函数,以及

int a = 0 ;
int b[9] ;
std__copy(&a , &a+1 , b) ;

这总是有效吗?


可能与https://dev59.com/AHHYa4cB1Zd3GeqPLW9W相同。 - MOHAMED
是的,尽管@MOHAMED的答案是关于数组的,但对于简单对象来说,原理是相同的。 - Mats Petersson
1
@MOHAMED,不,这不一样。对于数组的情况没有问题,但对于非数组变量,必须有特殊措辞。 - AProgrammer
从记忆中得出的答案是UB适用于C90和C++98,对于C11和C++11也是有效的,但我不记得这个澄清是否及时适用于C99和C++03 ;-( - AProgrammer
这个链接可能也很有用 https://dev59.com/Q2Qo5IYBdhLWcg3wOdFZ - MOHAMED
2个回答

17

是的,C99有特殊措辞表明,在处理地址时,任何给定对象 a 都会像一个只有1个元素的数组一样运行,因此 &a+1 是有效的 (§6.5.6/7):

对于这些运算符,在不是数组元素的对象上使用的指针与类型为该对象类型的只有1个元素长度的数组的第一个元素的指针相同。

虽然段落号不同 (§6.3.6),但 C90 给出了相同的要求。

C++ 在 §5.7/4 中也有相同的要求(C++03 和 C++11 的章节号相同)。

在 C++ 中,可以使用 std::less 比较任意对象 (相同类型) 的地址,即使内置的 < 操作符不产生有意义的结果 (例如,两个不属于同一数组的对象) (§20.8.5/7):

对于模板 greaterlessgreater_equal, 和 less_equal,专门用于任何指针类型的特化都产生一个全序,即使内置的操作符 <, >, <=, >= 不产生。

还要注意,虽然可以形成这些地址,并将它们与对象的地址进行比较,但是您不能引用这些指针 (如果尝试的话,编译器可能不会阻止您,但结果会是未定义的行为)。


有趣的是,我从来不知道 std::less 可以用于比较任意地址。标准究竟是如何保证这一点的? - chris

3

是的,在C++中可以保证(不确定C语言)。具体来说,类型为T的变量等价于具有相同类型的单个元素的数组,并且您始终可以获得超出数组末端的指针。


如果它具有与数组对象相同的原则,则必须在答案中提到禁止使用&a+1的指针解引用。 - MOHAMED
@MOHAMED:嗯,原帖没有对其进行取消引用,因此对答案也不是很相关 :) - jalf
我知道,只是想让他在使用这种行为时更加小心 :-) - MOHAMED
@MOHAMED:他的例子类似于std::copy,在该模板内部,end迭代器从未被解引用。你是对的,也许我应该更明确,但如果意图是将单个对象传递给一个处理范围(即迭代器对)的函数的实现,那么这是完全有效的。 - David Rodríguez - dribeas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接