指针之间的关系测试用于迭代,是安全的吗?

4
请考虑一个Thing数组。它是一种堆栈。 thingsBottom指向该数组,而空的一端则由thingsTop指向。
编辑:每次我想将东西推入列表中时,我会执行*thingsTop = newThing; thingsTop ++;
我想使用指针从后往前迭代它:
for (Thing* thing = thingsTop - 1; thing >= thingsBottom; thing--) {
    doSomething(*thing);
}

无论使用何种C实现,这个方法总是可靠的吗?

可以说thing >= thingsBottom是安全的吗?


@ThomasJager 这是一个牵强附会的重复问题,因为它没有涉及到数组。而且,请不要将 C++ 的帖子用作 C 的重复问题。 - Lundin
2个回答

5
这能保证始终有效,无论使用的具体C实现是什么吗?可以安全地说thing >= thingsBottom吗?
不是,不能完全保证。
您的方法存在问题,计算基于数组的指针值,在该指针之前的位置产生未定义的行为,只有指向同一数组或刚过其末尾的指针上进行的指针比较才是有效的。 "刚好在开始之前"没有任何特殊状态或约定。
您可以编写这样的循环;只需在递减之前进行测试即可:
for (Thing* thing = thingsTop; thing > thingsBottom; ) {
    thing--;
    doSomething(*thing);
}

3

由于两个指针都指向同一个数组,只有在这种情况下才能安全地将它们彼此比较。但是,如果你向数组下方移动一项,就会超出范围,这是未定义的行为,即使你不访问该项。

为了允许这样的代码,C语言有一个特殊规则,允许指针指向数组的下一个元素,只要在指针指向下一个元素时不对其进行引用即可。

这意味着你必须编写一个向上计数的循环,而不是向下计数的循环。一个相当经典的例子是:

thing* begin = thing_array;
thing* end   = thing_array + size; // point 1 past the last valid item

for(thing* i = begin; i != end; i++)
{
   do_stuff(i);
}

例如,这就是C++容器类::iterator的工作方式。
如果您真的需要从末尾开始迭代,我建议使用整数迭代器代替:
for(size_t i=0; i<size; i++)
{
  do_stuff(thing_array[size-i-1]);
}

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