C和C ++:数组元素访问指针vs int

如果您执行myarray[ i ]或将myarray[ i ]的地址存储在指针中,是否存在性能差异?

编辑:指针都在我的程序中一个不重要的步骤中计算,其中性能没有标准。 在关键部分期间,指针保持静态并且不被修改。 现在问题是这些静态指针是否比使用myarray[ i ]更快。

对于此代码:

 int main() { int a[100], b[100]; int * p = b; for ( unsigned int i = 0; i < 100; i++ ) { a[i] = i; *p++ = i; } return a[1] + b[2]; } 

在g ++中使用-O3优化构建时,声明:

 a[i] = i; 

产生了汇编输出:

 mov %eax,(%ecx,%eax,4) 

这句话:

 *p++ = i; 

制作:

 mov %eax,(%edx,%eax,4) 

所以在这种情况下,两者之间没有区别。 但是,这不是也不能成为一般规则 - 即使是略有不同的输入,优化器也可能生成完全不同的代码。

它可能完全没有任何区别。 编译器通常足够聪明,可以知道何时多次使用表达式并在适当时创建临时表达式。

编译器可以做出惊人的优化; 唯一知道的方法是读取生成的汇编代码。

使用GCC,使用-S ,使用-masm=intel作为Intel语法。

使用VC ++,使用/FA (IIRC)。

您还应该启用优化: -O2-O3使用GCC, /O2使用VC ++。

我更喜欢使用myarray[ i ]因为它更清晰,编译器更容易将其编译为优化代码。

使用指针时,编译器优化此代码会更复杂,因为很难确切地知道您使用指针做了什么。

应该没有太大的不同, 通过使用索引,您可以避免编译器的优化器倾向于所有类型的不同陷阱(别名是最重要的),因此我认为编译器的索引情况应该更容易处理。 这并不意味着你应该在循环之前处理上述事情,但循环中的指针通常只会增加复杂性。

是。 使用指针时,不会使用数组的初始地址计算地址。 它将直接访问。 因此,如果将地址保存在指针中,则可以提高性能。 但编译器通常会优化代码并在两种情况下都使用指针(如果你有静态数组)

对于动态数组(使用new创建),指针将为您提供更高的性能,因为编译器无法在编译时优化数组访问。

没有实质性的区别。 过早优化是万恶之源 – 在检查这样的微优化之前获取一个分析器。 此外,myarray [i]更容易移植到自定义类型,例如std :: vector。

好的,所以你的问题是,速度更快:

 int main(int argc, char **argv) { int array[20]; array[0] = 0; array[1] = 1; int *value_1 = &array[1]; printf("%d", *value_1); printf("%d", array[1]); printf("%d", *(array + 1)); } 

像其他人已经指出的那样,编译器可以进行巧妙的优化。 当然这取决于表达式的使用位置,但通常你不应该关心那些微妙的差异。 编译器可以certificate您的所有假设都是错误的。 今天你不应该关心这些差异。

例如,上面的代码生成以下(仅代码段):

 mov [ebp+var_54], 1 #store 1 lea eax, [ebp+var_58] # load the address of array[0] add eax, 4 # add 4 (size of int) mov [ebp+var_5C], eax mov eax, [ebp+var_5C] mov eax, [eax] mov [esp+88h+var_84], eax mov [esp+88h+var_88], offset unk_403000 # points to %d call printf mov eax, [ebp+var_54] mov [esp+88h+var_84], eax mov [esp+88h+var_88], offset unk_403000 call printf mov eax, [ebp+var_54] mov [esp+88h+var_84], eax mov [esp+88h+var_88], offset unk_403000 call printf 

简短回答:唯一可以确定的方法是对两个版本进行编码并比较性能。 如果存在可测量的差异,除非您在非常紧密的循环中进行大量的数组访问,否则我个人会感到惊讶。 如果这是在程序的生命周期中发生一次或两次的事情,或者取决于用户输入,则不值得担心。

请记住,表达式a[i]被评估为*(a+i) ,这是一个加法加解除引用,而*p只是一个解除引用。 但是,根据代码的结构,它可能没有什么区别。 假设如下:

 int a[N]; // for any arbitrary N > 1 int *p = a; size_t i; for (i = 0; i < N; i++) printf("a[%d] = %d\n", i, a[i]); for (i = 0; i < N; i++) printf("*(%p) = %d\n", (void*) p, *p++); 

现在我们将a[i]*p++进行比较,这是一个解除引用加上一个后增量(除了循环控制中的i++ ); 这可能会比数组下标更昂贵。 更不用说我们引入了另一个并非绝对必要的变量; 我们交易的空间很小,可能会有或没有提高速度。 这实际上取决于编译器,代码结构,优化设置,操作系统和CPU。

首先担心正确性,然后担心可读性/可维护性,然后担心安全性/可靠性,然后担心性能。 除非您未能满足严格的性能要求,否则请专注于使您的意图清晰易懂。 如果它给你错误的答案或执行了错误的操作,或者如果它在第一次输入错误时崩溃,或者如果你不能修复错误或添加新function而没有破坏,那么代码的速度并不重要一些东西。

是..当存储myarray[i]指针时,它会表现得更好(如果大规模使用……)

为什么??

它会为你节省一个额外的东西,可能是一个乘法(或一个class次..)

在静态内存分配的情况下,许多编译器可能会为您优化。 如果使用动态内存分配,编译器将不会优化它,因为它在运行时!