为啥 C 语言不支持列主数组? [关闭]

Posted

技术标签:

【中文标题】为啥 C 语言不支持列主数组? [关闭]【英文标题】:Why does C language not support column major array? [closed]为什么 C 语言不支持列主数组? [关闭] 【发布时间】:2013-01-07 18:18:08 【问题描述】:

这只是一个随机的设计选择还是 C 支持行优先而不是列优先的任何具体原因?我知道 Fortran 使用列专业。那么这些设计选择背后的原因(如果有的话)是什么?

【问题讨论】:

嗯,它必须是一个或另一个,所以为什么不 row-major 为什么 Fortran 不支持行专业? 为什么你的代码需要列专业? (通过转置你的算法,你可能会像内存一样高效......) 也许作者希望在他们自己的工作中从一种方法中获得某些优于另一种方法的好处:“同样,在行优先顺序中,最右边的索引随着连续内存位置的步进而变化,而在列主顺序最左边的索引变化更快。” en.wikipedia.org/wiki/Row-major_order @Tomas,我的代码不需要列专业。我只是对这些设计选择感到好奇。 【参考方案1】:

根据我对该问题的一些 cmets 以及其他一些答案(以及我自己的一些思考 - 但特别是对 C 语言设计过程一无所知......),我相信这是一个选择仅仅基于做出这个决定的人(里奇?)需要他们自己。

如果您将多维数组的索引解释为矩阵索引,则将第一个索引作为行索引,将第二个索引作为列索引是有意义的 - 即列优先结构。如果您的应用程序将大量使用线性代数或其他矩阵繁重的计算,那么以一种可以高效地一次遍历一列的方式存储这些结构也是有意义的,因为许多算法都这样做。出于这个原因,Matlab 和 Fortran 等编程语言受益于列优先 - 它可以更轻松地编写考虑到矩阵和矩阵算法的高效代码。

另一方面,C 比例如 C 更通用。 Matlab 或 Fortran。如果您不打算将int** 专门用于矩阵,那么哪个索引是哪个并不重要。如果aint**,那么a[2] 返回一个int*a[2][1] 返回一个int,这似乎很自然——你“深入挖掘”了多维数组。为了效率,我们现在只关心如果我们挑选出a[2] 并想要迭代它,它应该被有效地缓存。 无论您是程序员,是否将a[2] 与矩阵行或矩阵列相关联 - 我们不使用矩阵!

因此,没有充分的理由(我可以从我的脑海中弄清楚)C 是列主要的。在实现第一个版本时,可能更容易使其成为行优先 - 可能是因为底层的低级语言(汇编程序?)已经是行优先的 - 那就是那个。

【讨论】:

底线:Fortran 专注于数学,列优先布局使线性代数的实现更加优雅,而 C 专注于低层次,而“行优先”布局使其规范更加优雅。 还要注意int[][]int**是不同的。 @Tinctorius:这是总结我想说的非常好的方式。我想我太累了,无法优雅地表达 =) 关于int[][]int**,我很清楚它们并不完全相同。不过,对于这个例子,我认为这并不重要。 我认为这在某种程度上很重要。 int[n][m] 很像一个密集矩阵,k[i][j] 通过采用 (i*m+j)-th int 大小的单元格来取消引用。 int** 是指向指针的指针,因此 [i][j] 涉及取消引用两个指针。后者与行优先或列优先无关,但前者正是行优先(或:第一个索引中的专业,而不是最后一个索引)的含义。 我认为您第二段中的第一句话是错误的,我很确定这描述了一个行主要制度。【参考方案2】:

在C中数组元素保证是连续的内存元素,二维数组是数组的数组,所以说数组int a[10][20]a[0] 本身就是一个数组,它的元素必须是连续的。同样a[0]a[1] 相邻。

【讨论】:

【参考方案3】:

C 只定义数组,并允许数组的元素反过来也是数组。对于数组数组,第一个索引选择一个数组元素,第二个索引选择该数组中的一个值元素。颠倒它们的意思会产生不合逻辑的语法。

将第一个索引解释为行号,将第二个索引解释为某些二维矩阵数据结构的列号就是这样,一种解释。

请注意,Fortran 的(主要列)数组不是通过应用两个单独的索引运算符来索引的。

编辑:为了给出权威的引用,C 标准在 §6.5.2.1 (C99) 中解释了下标多维数组的结果如何是一个 n-1 维数组

由此数组以行优先顺序存储

(强调我的)

【讨论】:

对,但这并不能回答任何问题。 确实如此。当写 int y[4][3] = 1, 3, 5, 2, 4, 6, 3, 5, 7 ;我们有一个 4x3 矩阵的规范描述,它的第 0 行是 1、3、5。

以上是关于为啥 C 语言不支持列主数组? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

C语言基础:指针相关概念(指针的算术运算 指针数组指向指针的指针 传递指针给函数 从函数返回指针 )为啥C 语言不支持在调用函数时返回局部变量的地址?

为啥 C++11 不支持指定初始化列表作为 C99? [关闭]

为啥 C++11 不支持指定初始化列表作为 C99? [关闭]

为啥 Kotlin 不支持“三元运算符”[关闭]

C语言如何求一个二维数组有几行,还有为啥会提示gets()是一个未定义的标识符?

CString之间为啥不能互相赋值