常量指针数组还是指向数组的指针? C语言中什么更快?
你好,我现在正在上 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”是一个常量数组,编译器应该“知道”元素位置的本地化,以防使用指向该数组的变量指针,这可能需要更多的处理时间,另一方面搜索我想要显示的项目时,手可能会更快。更快/更小/优化的方法是什么?
先感谢您。
Hello I'm in an intermediary C class right now and this thought just came to my mind:
int multi[3][4]; // const multidimensional array
int* ptr = *multi; // ptr is a pointer variable that hold the address of multi const array
So, what is faster/smaller/optimized for access a multidimensional array position?
This:
multi[3][1]; // index the value position
or
*(*(multi+2)+1); // pointer to the position on the array
or (UPDATED)
ptr += 9; // pointer arithmetic using auxiliary pointer
Since "multi" is an const array the compiler should "know" already the localization of the element position, in case of using an variable pointer pointing to that array that could take more processing time, on the other hand could be faster when searching for the item that I want to display. What is the faster/smaller/optimized approach?
Thank you in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
它们都以相同的方式编译,
*(pointer_to_first_element + x + y)
。They're all compiled in the same way,
*(pointer_to_first_element + x + y)
.首先
不是 const 数组。该声明中没有任何
const
内容。其次,
将使
ptr
指向元素multi[0][0]
。数值上它与multi[0]
的地址和整个multi
的地址相同,但类型不同。第三,
根据定义,与 相同
,因此性能上不存在合理的差异。它与上面所说的有何联系尚不清楚。
第四,
其中没有任何“指针算术”。它相当于
普通的积分加法。同样,它与上面所说的内容有何联系尚不清楚。
最后,您的问题的标题为“常量指针数组或指向数组的指针”,而在问题的实际文本中我两者都没有看到。
Firstly
is not a
const
array. There is nothingconst
in this declaration.Secondly,
will make
ptr
point to the elementmulti[0][0]
. Numerically it is the same as the address ofmulti[0]
and the address of the entiremulti
, but the types are different.Thirdly,
is by definition the same as
so there can be no justified difference in performance. How it is connected to what was said above is not clear.
Fourthly,
has no "pointer arithmetic" in it whatsoever. It is equivalent to
which is an ordinary integral addition. Again, how it is connected to what was said above is not clear.
Finally, your question is titled as "Constant pointer array or pointer to an array", while in the actual text of the question I see neither.
如果你的代码被抛弃,那么无论你的代码有多快都没有关系,因为没有人能够理解和维护它;此外,棘手的代码有时会阻止编译器进行更好的优化。
例如:
我通过
gcc -c -g -Wa,-a,-ad > 运行了上面的内容foo.lst
以交错生成生成的程序集和源代码。这是
x = arr[2][3];
的翻译:这是
x = *(*(arr+2)+3);
的翻译:最后,
x = *(ptr + 11);
的翻译:不要试图超越你的编译器。现在已经不是 20 世纪 70 年代了。 gcc 知道如何有效地进行数组访问,而无需您告诉它。
您甚至不应该考虑此级别的性能除非您已经调整了算法和数据结构,在编译器上使用了最高的优化设置(FWIW,
-O1
为所有三个版本生成相同的代码),并且您仍然无法满足硬性能要求(在这种情况下,正确的答案通常是购买更快的硬件)。在没有首先通过分析器运行代码以找到真正的瓶颈之前,您不应该更改任何内容。 测量,不要猜测。编辑
当然,当文字
2
和3
被变量替换时,情况就会发生变化。在这种情况下,*(ptr + offset);
看起来效果最好。但幅度不大。我仍然认为在这个层面上清晰度更重要。It doesn't matter how fast your code is if it gets tossed because nobody else can understand and maintain it; also, tricky code can sometimes prevent your compiler from making a better optimization.
For example:
I ran the above through
gcc -c -g -Wa,-a,-ad > foo.lst
to get the generated assembly and source code interleaved.Here's the translation for
x = arr[2][3];
:Here's the translation for
x = *(*(arr+2)+3);
:And finally, the translation for
x = *(ptr + 11);
:Don't try to outsmart your compiler. This isn't the 1970s anymore. gcc knows how to do array accesses efficiently without you having to tell it.
You shouldn't even be thinking about performance at this level unless you've tuned your algorithm and data structures, used the highest optimization settings on your compiler (FWIW,
-O1
generates the same code for all three versions), and you're still failing to meet a hard performance requirement (in which case, the right answer is usually to buy faster hardware). And you shouldn't change anything without first running your code through a profiler to find the real bottlenecks. Measure, don't guess.EDIT
Naturally, when the literals
2
and3
are replaced by variables, the situation changes. In that case, the*(ptr + offset);
comes out looking the best. But not by much. And I'll still argue that clarity matters more at this level.a[i]
表示*(a+i)
,其实也可以写i[a]
你的编译器会接受它。无论如何,理论上,*(ptr+i) 可能比 ptr[j][k] 稍快一些,因为您正在执行一次加法(而
ptr [j][k]
可能需要 2)。a[i]
means*(a+i)
, in fact you can also writei[a]
and your compiler will accept it.*(ptr+i)
anyway could be slightly faster thanptr[j][k]
in theory, since you're doing a single addition (whileptr[j][k]
could require 2).我不确定 const 数组来自哪里,但为了讨论,我们假设原始帖子中有一些。
由于原始发布者没有明确提及 PC 编程,const 数组和常规数组不一定以相同的方式编译。
在嵌入式系统中,如果 const 数组分配在真正的非易失性存储器(即具有真正 ROM 的嵌入式应用程序)中,则 const 数组可能比非 const 数组慢。速度慢与 ROM 的访问时间有关,并且与硬件高度相关。
关于指针运算,这是访问数组的唯一方法。 C语言中的数组语法就是编译器人所说的“语法糖”,即只是为了看起来而已。 这样的数组访问
像arr[i]
被编译器翻译为
*(arr+i)
,它们在性能和功能上是等效的。
I'm not sure where the const arrays came from, but for the discussion, lets assume there were some in the original post.
As the original poster didn't explicitly mention PC programming, const arrays and regular arrays are not necessarily compiled in the same way.
In embedded systems, const arrays may be slower than non-const ones, if the const arrays are allocated in true non-volatile memory, ie an embedded application with real ROM. The slowness is related to access times of the ROM, and highly hardware-specific.
Regarding pointer arithmetic, that is the only way to access arrays. The array syntax in the C language is what the compiler people call "syntactic sugar", i.e it is just there for looks. An array access like
arr[i]
is translated by the compiler to
*(arr+i)
and they are equivalent in performance and function.