为了初始化100×100二维数组的所有元素,我们可以用两种方式完成:
方法1:
int a[100][100];
for(i=0; i<100; i++){
for(j=0; j<100; j++){
a[i][j] = 10;
}
}
方法2:
int a[100][100];
for(j=0; j<100; j++){
for(i=0; i<100; i++){
a[i][j] = 10;
}
}
现在我的问题是哪种方法更有效,为什么?
答案 0 :(得分:8)
第一种方法,因为它将按顺序访问数组。
C以 row-major 顺序存储二维数组,这意味着a [i] [j]将与[i] [j + 1]相邻但不会与[a]相邻I + 1] [j]的。
另一种说同样的事情(概括为&gt; 2维)的方法是最右边的索引在内存中相邻。或者,递增索引意味着您必须跳过正在递增的索引右侧的所有维度。
答案 1 :(得分:2)
C11 standard,第6.5.2.1.3节表明存储了数组row-major。这意味着第一种方法是顺序访问内存,而第二种方法不是。 根据您的CPU缓存机制,RAM访问机制和阵列的尺寸,可以更快。但一般来说,我会说第一种方法更快。
答案 2 :(得分:1)
当你声明一个像int a[100][100]
这样的数组时,它的内存布局是相同的,如果你声明int a[10000]
,这意味着你可以连续访问所有单元格,如果你只是迭代一个。
标准表明数组是按行存储的,这意味着内存中的前100个单元格将是a[0][0]
到a[0][99]
,然后是a[1][0]
到a[1][99]
。
在大多数CPU上,第一种方法会更快,因为CPU可以将(大部分)阵列加载到CPU缓存中,从而快速访问它。请注意,这可能因CPU而异。
答案 3 :(得分:1)
我怀疑两个循环的速度是相同的,实际上生成的代码是相同的。除非数组是易失性的,否则编译器可以自由切换循环,并且应该将它们切换到对目标机器更好的顺序。
答案 4 :(得分:0)
这取决于您使用的语言是row-major还是列专业。内存中的任何内容总是以一维方式布局,因此所有2D内容也以一维方式转换。 现在请注意,有两种方法可以做到这一点。
i *(连续元素的数量)+ j 我在哪里排第一。和j是列号
i *(列中元素的数量)+ j 其中i是列号,j是行号。
所以这里首先是一种将2D数组转换为1D方式的行主要方式,第二种方式是列主要方式。像C / C ++这样的语言是行主要的,所以它们遵循第一种方式。
现在观察一下,根据行中元素的数量,你有点,(0,0)和(1,0),但是(0,0)和(0,1) )是相邻的。
作为最终答案,您的问题取决于编程语言,无论它是行主要编程语言还是列专业。 在C / C ++中,因为它们是行主要的,所以第一个会更快。