使用指针比使用C中的数组语法要快得多吗?

时间:2010-11-14 13:49:37

标签: c arrays pointers performance

使用当前的C编译器,使用数组语法(a [i])比使用指针(*(p + i))还慢吗?

10 个答案:

答案 0 :(得分:11)

它们完全相同。数组访问是指针数学的语法糖。

答案 1 :(得分:9)

他们应该是一样的。但是:

for( i = 0; i < ...; ++ i ) ... array[i] ...

可能比以下慢:

for( p = array; *p; ++ p ) ... *p ...

因为在前一种情况下,编译器可能需要执行*(array+i),而在第二种情况下,您只需执行(*p)

然而,在普通情况下,编译器应该能够优化并生成相同的机器代码。

答案 2 :(得分:8)

不,根据C和C ++标准,a[i]的定义相当于*(a+i)。这也意味着a[1]相当于1[a]。试试吧:))

答案 3 :(得分:5)

地狱不! a[i]始终等同于*(a+i)

a[i] = *(a + i) = *(i + a) =i[a];

答案 4 :(得分:3)

在x86或x86_64上,使用p[i]*(p+i)(注意:这两种形式在C语言中是相同的)可能比在循环的每一步递增p更快,假设您需要将i保留为其他目的。 x86架构具有高效的基址/偏移量使用寻址方式,包括以2的小功率缩放偏移量。

另一方面,如果您可以通过递增i来消除p,则可以减少循环中所需的寄存器数量,这可以允许进一步优化。以下是关于x86上各种情况下相对成本的一些快速思考:

  • 如果数组a在非PIC编译的代码中具有静态存储持续时间(staticextern全局),则a[i]*p(没有i)方法使用相同数量的寄存器(例如0xdeadbeef(,%ecx,4) vs (%esi))。
  • 如果您的数组a是自动的(本地堆栈变量)而不是可变长度数组,则a[i]*p方法使用相同数量的寄存器(例如{{1 } {} 12(%esp,%ecx,4)其中(%esi),堆栈指针,无论如何都已保留。)
  • 如果您的数组%esp具有静态存储持续时间且您的代码编译为PIC,a可能比a[i]方法贵得多,即使您必须保留{{无论如何,还是为了另一个目的。
  • 如果数组*p不是当前作用域中的数组变量,而是指向从其他位置传递给函数的数组的指针,则ia多一个寄存器(例如a[i] vs *p)。

答案 5 :(得分:2)

在某些情况下可能会出现类似

的情况
while (*s++ = *d++)
   ;

可能比

更快
while (s[i] = d[i])
   i++;

但即使这样也可能会被优秀的编译器优化掉。

答案 6 :(得分:1)

编译器无论如何都会将它们转换为指针代码,它只是使它们更容易使用。

将数组运算符视为等效指针的内联函数。

答案 7 :(得分:1)

它们是等价的。但是使用数组语法的算法通常是编写的

int a[];
for (int n = 0; n < size; n++) { ... Do stuff with a[n]; }

每次访问a而不是

的元素时,需要再添加一个
int a[size];
int *end = a + size;
for (int *i = a; i != end; ++i) { ... Do the same stuff with *i ; }

有些编译器可能会将第一个版本优化为第二个版本。

答案 8 :(得分:1)

很明显,这不是他的意思,这应该有所帮助。

// which is faster? *t or t[i]?
process_some_array(T *t, size_t n)
{
    T *end = &t[n];
    for (T *t = t; t < end; ++t)
        // do stuff with *t
    for (size_t i = 0; i < n; ++i)
        // do stuff with t[i]
}

答案不是只要您的编译器没有任何优化。对于一般情况,您不应该担心差异,因为如果存在则微不足道。此外,对于您自己和您的同事来说,通常更容易解析和调试。

如果这不是你的意思,我担心这是一个愚蠢的问题,请参阅其他答案。

答案 9 :(得分:0)

指针和数组都通过address访问.Array表现得像一个常量指针和指针,用于保存任何值的地址。所以同样的事情是通过地址访问值。由于这两者完全相同。