【问题标题】:How can I best iterate over a C array? With pointers or by index? [duplicate]如何最好地迭代 C 数组?用指针还是按索引? [复制]
【发布时间】:2016-04-29 05:43:49
【问题描述】:

我经常看到人们使用指针迭代 C 样式数组,而我发现使用索引更易读。下面的例子说明了我考虑的两种方式。它们不会导致相同的拆卸...

我的问题:使用“跑步者”而不是索引是否有利?顺便问一下,“跑步者”技术还有别的名字吗?

它是否取决于底层类型,例如int、char 还是结构体?

struct somestruct
{
    float f;
    int i;
};

const unsigned int uiSize = 10000;
somestruct * myarray = new somestruct[uiSize];
const somestruct * const pEnd = myarray + uiSize;

// way 1: runner
somestruct * pRunner = myarray;
while(pRunner < pEnd)
{
    pRunner->f += 5;
    pRunner->i += 5;
    ++pRunner;
}

// way 2: index
unsigned int ui = 0;
for (ui = 0; ui < uiSize; ++ui)
{
    myarray[ui].f += 6;
    myarray[ui].i += 4;
}

【问题讨论】:

  • 这是 C++ 而不是 C。我认为您的意思是“数组”而不是“向量”。
  • 不是都一样吗?
  • 好的,它是 C++。问题保持不变。
  • @SouravGhosh 否 - 数组和向量不是一回事。 C++ 两者都有,而且它们的行为不同

标签: c performance pointers


【解决方案1】:

使用整数索引还是指针都没有关系。但是,您提供的两个示例都没有遵循 C(或 C++)中的标准做法。这是一个重写:

// way 1: runner
for (somestruct * pRunner = myarray; pRunner != pEnd; ++pRunner)

// way 2: index
for (size_t ui = 0; ui < uiSize; ++ui)

当简单地迭代容器的所有元素时,我们总是使用for循环,而不是while循环,因为它更简洁和惯用(意味着每个人都这样做,所以每个人都可以快速阅读) .

【讨论】:

  • “没关系”——虽然我同意你的观点,但 IMO 你应该指出这两种方式在语义上是等效的。
【解决方案2】:
array[index]

这与*(array + index) 相同(在C 中)。因此,除了增加index 之外,您还需要添加一些* 以获取要取消引用的指针array + index。当您直接递增指针时,不需要这种额外的添加。

*) 我希望任何体面的编译器都能在每次迭代时将其降低为 single 加法(并将结果缓存在某个寄存器或堆栈中)。对于一个好的编译器,我希望它能够识别这种模式并生成等同于直接使用指针的代码。

最后的评论:除非你在一个非常紧密的循环中使用它并且你的编译器能够生成像样的代码并且你的profiler 告诉你这是你的性能瓶颈,更喜欢更容易理解和阅读的解决方案。

【讨论】:

  • "直接递增指针时不需要他。"如果不是加法(按 sizeof 1 项),那么您认为指针增量是什么?
  • @Lundin 使用指针增加一个“事物”,使用索引增加索引并将索引添加到基指针。因此,两个添加对一个。
  • 无论使用哪种方法,您都可以将基地址加载到索引寄存器中。不同之处在于,使用数组方法时,会保留包含基地址的索引寄存器,然后将其与值相加并将结果存储在不同的索引寄存器中。使用指针方法,您可以通过将加法结果存储在同一寄存器中来更改索引寄存器。在通用计算机上,为什么一种形式比另一种形式更快并不明显。很可能没有区别,或者至少没有值得一提的。
  • 也就是说,编译器(希望)没有那么愚蠢,以至于每次访问数组时它都会从 RAM 中获取数组的基地址。
  • @Lundin 当然,这里的性能没有“真正的”差异(主要归功于智能编译器,我试图在回答的后半部分指出这一点)。但是,在语义上有所不同。
猜你喜欢
  • 1970-01-01
  • 2011-06-04
  • 2017-02-09
  • 2018-08-07
  • 2011-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多