3

您好,我现在正在上中级 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 数组,编译器应该“知道”元素位置的本地化,如果使用指向该数组的变量指针可能需要更多处理时间,另一方面在搜索时可能会更快我要显示的项目。什么是更快/更小/优化的方法?

先感谢您。

4

5 回答 5

8

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

于 2011-01-25T18:38:35.037 回答
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;

这是一个普通的积分加法。同样,它与上述内容的关系尚不清楚。

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

于 2011-01-25T19:02:15.750 回答
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)

不要试图智取你的编译器。这已经不是 1970 年代了。gcc 知道如何有效地进行数组访问,而无需您告诉它。

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

编辑

自然,当字面量23被变量替换时,情况就会发生变化。在这种情况下,*(ptr + offset);出来的效果最好。但不是很多。我仍然会认为,在这个级别上,清晰度更重要。

于 2011-01-25T20:54:58.363 回答
2

a[i] 意思是 *(a+i),实际上你也可以编写i[a]并且你的编译器会接受它。

*(ptr+i)无论如何可能比ptr[j][k]理论上要快一些,因为你正在做一个单一的添加(虽然ptr[j][k]可能需要 2 个)。

于 2011-01-25T18:42:12.450 回答
1

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

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

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


关于指针算法,这是访问数组的唯一方法。C 语言中的数组语法是编译器人们所说的“语法糖”,即它只是为了外观。数组访问,如

ar[i]

由编译器翻译成

*(arr+i)

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

于 2011-01-25T20:57:19.173 回答