One-past-end-of-object pointers

One-past-end-of-object pointers

本文关键字:pointers One-past-end-of-object      更新时间:2023-10-16

我知道指针比较只有在两个指针指向某个"进入"分配给同一对象的存储空间,或者if它们是NULL,或者是对象的后一项,只要它不是反向引用。

我用的"object"是标准的" C "意思。

对于两个指针的比较是否有特殊的分配每一个都超过了物体的末端比较过一次结束的指针和派生的指针表达式引用实际对象。给定以下定义:

 char arr[100];
 char *pend = &arr[99];
 char *pa = pend+1;
 char *pb = pend+1;

是保证有意义的比较pa == pb,或者保证有意义调用UB,因为- pa和- pb都不指向arr。

换句话说,从标准的角度来看,是否存在比较pa和pb的语义差异,比如pa和&arr[99]+1 ?这似乎是显而易见的,但是:)

这是一个很好的例子,说明为什么你不应该把你的问题标记为C和c++:

对于C,这是标准所涵盖的。

6.5.9相等运算符

6两个指针比较相等当且仅当这两个都是空指针,它们都是指向同一个对象(包括一个指向对象的指针和子对象的开始)或函数,都是指向同一数组对象的一个过去的最后一个元素,或者一个是一个指向一个过去的最后一个数组对象,另一个是一个指向不同的数组对象的开始发生立即跟随第一个数组对象地址空间。

对于c++,就不那么清楚了:

5.10平等运营商(expr.eq)

1 ==(等于)和!=(不等于)操作符具有与关系操作符相同的语义限制、转换和结果类型,除了它们的优先级较低和真值结果。[注:当a<bc<d具有相同的真值时, a<b == c<dtrue。——end note]相同类型的指针(指针转换后)可以比较是否相等。当且仅当两个相同类型的指针都为空、都指向同一个函数、或都表示相同的地址(3.9.2)时,它们比较相等。

从技术上讲,我看不出标准为什么要求两个过尾指针表示相同的地址。我可以找到标准要求对象具有地址的地方,并且&操作符返回该特定地址(因此两次获取地址会产生相同的指针值),但是经过结束的指针不指向对象,因此不适用。它们可以是不同的,只要减法可以返回到相同的数组基。

实际上,你不必担心这个问题,它在c++中和C中一样有效。

更新:根据JohnB的回答和那里的注释,c++标准可能打算更明确地要求这一点,但它确实间接地要求它。

在c++中,只保证正向迭代器:

24.2.5正向迭代

类或指针类型X满足前向迭代器的要求[…类型X的]对象提供多通道保证,如下所述。[…]

前向迭代器的==域是对象上的迭代器的域相同的底层序列。[…]

2类型X的可解引用迭代器a和b提供多遍历保证如果:

- a == b暗示++a == ++b和[…]

从24.4.1(指针的iterator_traits专门化)可以得出,指针是随机访问迭代器,因此是前向迭代器。

对于数组,如果pq都指向数组的最后一个元素,则可以从下面的语句中隐式地推断出(p+1) == (q+1):

5.7加性运算符[…]此外,如果表达式P指向数组的最后一个元素对象,则表达式(P)+1指向数组的最后一个元素的后面数组对象,如果表达式Q指向最后一个元素的后面,表达式(Q)-1指向数组对象的最后一个元素数组对象。

隐含地假设存在一个明确定义的地址,表示"最后一个元素的后面"。(数组是线性的,"one past the last element"包括线性事物数组被扩展的虚构,而线性事物的自然扩展又是线性的,因此只能有一个事物"one past the last element"。请注意标准在"one past the last element"和其他地方的"past the last element"之间的区别。