使用当前的C编译器,使用数组语法(a [i])比使用指针(*(p + i))还慢吗?
答案 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)
。
答案 4 :(得分:3)
在x86或x86_64上,使用p[i]
或*(p+i)
(注意:这两种形式在C语言中是相同的)可能比在循环的每一步递增p
更快,假设您需要将i
保留为其他目的。 x86架构具有高效的基址/偏移量使用寻址方式,包括以2的小功率缩放偏移量。
另一方面,如果您可以通过递增i
来消除p
,则可以减少循环中所需的寄存器数量,这可以允许进一步优化。以下是关于x86上各种情况下相对成本的一些快速思考:
a
在非PIC编译的代码中具有静态存储持续时间(static
或extern
全局),则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
不是当前作用域中的数组变量,而是指向从其他位置传递给函数的数组的指针,则i
比a
多一个寄存器(例如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表现得像一个常量指针和指针,用于保存任何值的地址。所以同样的事情是通过地址访问值。由于这两者完全相同。