【问题标题】:Is it safe to test relations between pointers for iteration?测试迭代指针之间的关系是否安全?
【发布时间】:2019-06-14 11:38:53
【问题描述】:

请考虑Thing 的数组。这是一种堆栈。

它被thingsBottom指向,它的空端被thingsTop指向。

编辑:每次我想将某些内容添加到列表中时,我都会使用*thingsTop = newThing; thingsTop++;

我想用指针从头到尾迭代它,像这样:

for (Thing* thing = thingsTop - 1; thing >= thingsBottom; thing--) {
    doSomething(*thing);
}

无论使用何种特定的 C 实现,这是否保证始终有效?

thing >= thingsBottom安全吗?

【问题讨论】:

  • @ThomasJager 这是一个牵强附会的骗局,因为它不涉及数组。无论如何,请不要将 C++ 帖子用作 C 帖子的骗子。

标签: c pointers iteration


【解决方案1】:

这是否保证始终有效,无论特定的 C 使用的实现?

thing >= thingsBottom安全吗?

不,也不是无条件的。

您的方法的问题在于,它会产生未定义的行为来计算指针值,该指针值将在该指针所基于的数组的开头之前,并且指针比较仅对指向或刚刚超过结尾的指针有效的,同一个数组。 “刚开始之前”没有任何特殊地位或规定。

可以写这样一个循环;您只需要在减量之前进行测试:

for (Thing* thing = thingsTop; thing > thingsBottom; ) {
    thing--;
    doSomething(*thing);
}

【讨论】:

    【解决方案2】:

    鉴于两个指针都指向同一个数组 - 只有这样 - 将它们相互比较是安全的。但是,如果您在数组下方移动 1 项,则即使您不访问该项,也会超出范围,这是未定义的行为。

    为了允许这样的代码,C 有一个特殊的规则,允许你有一个指针指向数组之外的 1 项,而且它是安全的,只要你不取消引用当它指向 1 个项目之外时的那个指针。

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

    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]);
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-07
      • 2011-02-13
      • 1970-01-01
      • 1970-01-01
      • 2010-10-30
      • 2015-10-14
      • 1970-01-01
      相关资源
      最近更新 更多