C 哪段代码更有效?

C 哪段代码更有效?,c,performance,C,Performance,对于初始化100×100二维数组的所有元素,我们可以通过两种方式进行初始化: 方法1: int a[100][100]; for(i=0; i<100; i++){ for(j=0; j<100; j++){ a[i][j] = 10; } } inta[100][100]; 对于(i=0;i第一个方法,因为它将按顺序访问数组 C按行大顺序存储二维数组,这意味着a[i][j]将与a[i][j+1]相邻,但与a[i+1][j]不相邻 还有另一种说法(推

对于初始化100×100二维数组的所有元素,我们可以通过两种方式进行初始化:

方法1:

int a[100][100];
for(i=0; i<100; i++){
    for(j=0; j<100; j++){
        a[i][j] = 10;
    }
}
inta[100][100];

对于(i=0;i第一个方法,因为它将按顺序访问数组

C按行大顺序存储二维数组,这意味着a[i][j]将与a[i][j+1]相邻,但与a[i+1][j]不相邻


还有另一种说法(推广到>2维)最右边的索引在内存中是相邻的。或者,增加索引意味着您必须跳转到要增加的索引右侧的所有维度。

第6.5.2.1.3节指示存储数组。这意味着第一种方法是按顺序访问内存,而第二种方法不是。取决于CPU的缓存机制、RAM访问机制和数组的大小,这两种方法都可能更快。。不过,一般来说,我会说第一种方法更快。

当您声明一个类似
int a[100][100]的数组时,它的内存布局与声明
int a[10000]时的内存布局相同
这意味着,如果您只需在a上迭代,就可以连续访问所有单元格

该标准表明数组是按行存储的,这意味着内存中的前100个单元格将是
a[0][0]
a[0][99]
然后是
a[1][0]
a[1][99]


在大多数CPU上,第一种方法会更快,因为CPU将能够加载(大多数)请注意,这可能在不同的CPU之间有所不同。

我怀疑两个循环的速度相同,事实上生成的代码是相同的。除非数组是可变的,否则编译器可以自由切换循环,并且应该将它们切换到任意顺序对于目标机器来说更好。

这取决于您使用的语言是a专业还是列专业。内存中的任何内容都是以一维方式排列的,因此所有2D内容也会以一维方式转换。 现在请注意,有两种方法可以做到这一点

  • i*(一行中的元素数量)+j 其中i是行号,j是列号

  • i*(列中元素的数量)+j 其中i是列号,j是行号

  • 这里第一种是将二维数组转换为一维数组的行主方式,第二种是列主方式。像C/C++这样的语言是行主方式,所以它们遵循第一种方式

    现在注意,在第一种方式中,根据行中元素的数量,点(0,0)和(1,0)非常远,但是(0,0)和(0,1)是相邻的

    所以作为最后的答案,您的问题取决于编程语言,无论它是行主编程语言还是列主编程语言。
    在C/C++中,因为它们是row-major,所以第一种方法会更快。

    你不能说第一种方法更快(甚至可以获得5张赞成票!)。这肯定取决于硬件体系结构。@Shahbaz:原则上,你是对的。在实践中,你能给我举一个跨步内存访问比顺序内存访问快的体系结构的例子吗?想象一下,一个体系结构中,多段ram可以与一个mu同时读入缓存lticore CPU,按顺序读取这些部分。我不喜欢特定的供应商产品,但这种情况比简单的80年代计算机更接近当今的现实,在这种情况下,顺序读取肯定意味着更快,或者可以使用
    memset((void*)a,10,sizeof a)
    并且不必担心行主顺序与列主顺序。@JohnBode,首先不需要强制转换,其次这不符合问题的要求。它将数组的每个字节设置为
    10
    。从技术上讲,你所做的不是初始化,而是赋值。@JensGustedt:argh。咖啡因不够。你是对的。不值得ting说这在C11中不是什么新鲜事;它一直都是这样。而且,它不是显式的;这只是C没有“多维数组”,只有“数组数组数组”这一事实的结果,而括号在声明和取消引用中的绑定方式导致了“行主数组”顺序。@R…,是的,我刚才提到C11是因为其他标准中的章节号可能不同。但这些长期存在的章节的内容实际上是相同的。没问题。我只是想提一下,以免有人误解你的答案,认为这是新的C11要求。
    int a[100][100];
    for(j=0; j<100; j++){
        for(i=0; i<100; i++){
            a[i][j] = 10;
        }
    }