它只是一个随机的设计选择,还是 C 支持行优先而不是列优先的任何具体原因?我知道 Fortran 使用列专业。那么这些设计选择背后的原因(如果有的话)是什么?
3 回答
基于我对问题的一些评论以及其他一些答案(以及我自己的一些反思 - 但特别是对 C 语言设计过程一无所知......),我相信这是一个仅基于做出这个决定的人(里奇?)需要什么。
如果将多维数组的索引解释为矩阵索引,则将第一个索引作为行索引,将第二个索引作为列索引是有意义的 - 即列优先结构。如果您的应用程序将大量使用线性代数或其他矩阵繁重的计算,那么以一种可以高效地一次遍历一列的方式存储这些结构也是有意义的,因为许多算法都这样做。出于这个原因,诸如 Matlab 和 Fortran 之类的编程语言受益于列优先——它使编写高效的代码变得更容易,同时考虑到矩阵和矩阵算法。
另一方面,C 比 Matlab 或 Fortran 更通用。如果您不打算int**
专门用于矩阵,那么哪个索引是哪个并不重要。a
if is an int**
, thena[2]
返回 anint*
并a[2][1]
返回 an似乎很自然int
——您“深入”地挖掘多维数组。为了效率,我们现在只关心如果我们选择a[2]
并想要迭代它,它应该被有效地缓存。无论您是程序员,是a[2]
与矩阵行还是矩阵列相关联都没有关系 - 我们不使用矩阵!
因此,没有充分的理由(我可以从我的头顶看出)C 是列主要的。在实现第一个版本时,将其设为行优先可能更容易——也许是因为底层的低级语言(汇编程序?)已经是行优先的——就是这样。
在 C 中,数组元素保证是连续的内存元素,二维数组是数组的数组,比如数组int a[10][20]
;a[0]
本身就是一个数组,它的元素必须是连续的。同样a[0]
与 相邻a[1]
。
C 只定义数组,并允许数组的元素反过来也是数组。对于数组数组,第一个索引选择一个数组元素,第二个索引选择该数组中的一个值元素。将它们的含义颠倒过来会产生不合逻辑的语法。
将第一个索引解释为行号,将第二个索引解释为某些 2D 矩阵数据结构的列号就是这样,一种解释。
请注意,Fortran 的(主要列)数组不是通过应用两个单独的索引运算符来索引的。
编辑:为了给出权威引用,C 标准在 §6.5.2.1 (C99) 中解释了下标多维数组的结果如何是一个 n-1 维数组之后
由此得出,数组以行优先顺序存储
(强调我的)