常量指针数组或指向数组的指针?什么是更快的C?

时间:2011-01-25 18:35:40

标签: c arrays pointers pointer-arithmetic

你好,我现在正在中介C班,我想到了这个想法:

int multi[3][4]; // const multidimensional array

int* ptr = *multi; // ptr is a pointer variable that hold the address of multi const array

那么,访问多维数组位置的更快/更小/优化是什么?

此:

multi[3][1]; // index the value position

*(*(multi+2)+1); // pointer to the position on the array

或(更新)

ptr += 9; // pointer arithmetic using auxiliary pointer

由于“multi”是一个const数组,编译器应该“知道”元素位置的本地化,如果使用指向该数组的变量指针可能需要更多的处理时间,另一方面可能会更快搜索我想要显示的项目时。什么是更快/更小/优化的方法?

提前谢谢。

5 个答案:

答案 0 :(得分:8)

它们都以相同的方式编译,*(pointer_to_first_element + x + y)

答案 1 :(得分:6)

首先

int multi[3][4];

不是const数组。此声明中没有const

其次,

int* ptr = *multi;

会使ptr指向元素multi[0][0]。数字上它与multi[0]的地址和整个multi的地址相同,但类型不同。

第三,

multi[3][1];
根据定义,

相同
*(*(multi + 3) + 1);

所以性能上没有任何合理的差异。如何与上述内容联系起来并不清楚。

第四,

*ptr + 9;

其中没有“指针算术”。它相当于

multi[0][0] + 9;

这是普通的整体添加。再次,它与上述内容的联系方式尚不清楚。

最后,您的问题标题为“常量指针数组或指向数组的指针”,而在问题的实际文本中,我看不到。

答案 2 :(得分:4)

如果你的代码被抛出的速度有多快并不重要,因为没有其他人可以理解和维护代码;此外,棘手的代码有时会阻止编译器进行更好的优化。

例如:

int main(void)
{
  int arr[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
  int *p = *arr; // == arr[0] == &arr[0][0]

  int x;

  x = arr[2][3];         // Straightforward array access
  x = *(*(arr+2)+3);     // Ugly pointer arithmetic
  x = *(ptr + 11);       // Slightly less ugly pointer arithmetic

  return 0;
}

我通过gcc -c -g -Wa,-a,-ad > foo.lst运行上面的内容,以使生成的程序集和源代码交错。

以下是x = arr[2][3];的翻译:

movl      -16(%ebp), %eax     
movl      %eax, -8(%ebp)      

以下是x = *(*(arr+2)+3);的翻译:

leal      -60(%ebp), %eax
addl      $44, %eax
movl      (%eax), %eax
movl      %eax, -8(%ebp)

最后,x = *(ptr + 11);的翻译:

movl      -12(%ebp), %eax
addl      $44, %eax
movl      (%eax), %eax
movl      %eax, -8(%ebp)

不要试图超越你的编译器。这不再是20世纪70年代了。 gcc知道如何有效地进行数组访问,而无需告诉它。

你甚至不应该思考关于这个级别的性能,除非你已经调整了算法和数据结构,在编译器上使用了最高的优化设置(FWIW) ,-O1为所有三个版本生成相同的代码),并且仍然无法满足硬性能要求(在这种情况下,正确的答案通常是购买更快的硬件) 。如果没有先通过分析器运行代码来找到真正的瓶颈,就不应该更改任何测量,不要猜。

修改

当然,当文字23被变量替换时,情况会发生变化。在这种情况下,*(ptr + offset);看起来最好。但不是很多。而且我仍然认为清晰度在这个层面更重要。

答案 3 :(得分:2)

a[i] 表示 *(a+i),实际上您也可以编写i[a],您的编译器也会接受它。

无论如何,

*(ptr+i)在理论上可能比ptr[j][k]略快,因为你只做了一次加法(而ptr[j][k]可能需要2)。

答案 4 :(得分:1)

我不确定const数组的来源,但是对于讨论,我们假设原始帖子中有一些。

由于原始海报未明确提及PC编程,因此const数组和常规数组不一定以相同的方式编译。

在嵌入式系统中,如果const数组分配在真正的非易失性存储器(即具有真实ROM的嵌入式应用程序)中,则const数组可能比非const数组慢。这种缓慢与ROM的访问时间有关,而且与硬件特定有关。


关于指针运算,这是访问数组的唯一方法。 C语言中的数组语法是编译器所谓的“语法糖”,即它只是用于外观。像

这样的数组访问

ARR [I]

由编译器翻译为

*(ARR + I)

它们在性能和功能上是相同的。