0

100×100の2次元配列のすべての要素を初期化するには、次の2つの方法で実行できます。

方法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;
    }
}

今私の質問は、どちらの方法がより効率的で、なぜですか?

4

5 に答える 5

8

最初の方法は、配列に順番にアクセスするためです。

Cは、2次元配列を行優先順に格納します。つまり、a[i][j]はa[i][j + 1]に隣接しますが、a [i +1][j]には隣接しません。

同じこと(2次元以上に一般化される)を言うさらに別の言い方は、右端のインデックスがメモリ内で隣接しているということです。または、インデックスをインクリメントするということは、インクリメントするインデックスの右側にあるすべてのディメンションを飛び越えなければならないことを意味します。

于 2012-06-07T13:38:03.767 に答える
2

C11標準のセクション6.5.2.1.3は、配列が優先で格納されることを示しています。これは、最初の方法がメモリに順番にアクセスしているのに対し、2番目の方法はそうではないことを意味します。CPUのキャッシュメカニズム、RAMアクセスメカニズム、およびアレイのサイズに応じて、どちらかが高速になる可能性があります。ただし、一般的には、最初の方法の方が高速です。

于 2012-06-07T13:40:03.627 に答える
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によって異なる場合があることに注意してください。

于 2012-06-07T13:46:40.713 に答える
1

両方のループが同じ速度であり、実際に生成されたコードが同一であると思われます。配列が揮発性でない限り、コンパイラーはループを自由に切り替えることができ、ターゲットマシンに適した順序にループを切り替える必要があります。

于 2012-06-07T14:11:13.687 に答える
0

使用している言語が行メジャーか列メジャーかによって異なります。メモリ内のすべてのものは常に1次元で配置されるため、すべての2Dのものも1Dで変換されます。これを行うには2つの方法があることに注意してください。

  1. i *(行の要素数)+ jここで、iは行番号です。jは列番号です。

  2. i *(列の要素数)+ jここで、iは列番号、jは行番号です。

したがって、ここで最初の方法は2D配列を1Dの方法に変換する行を主な方法であり、2番目の方法は列を主な方法です。C / C ++のような言語は行優先であるため、最初の方法に従います。

ここで、最初の方法で、行の要素の数に応じて非常に遠い点(0,0)と(1,0)がありますが、(0,0)と(0,1)は隣接していることに注意してください。 。

したがって、最終的な答えとして、質問はプログラミング言語によって異なります。これは、行が主要なプログラミング言語であるか、列が主要なプログラミング言語であるかによって異なります。C / C ++では、行がメジャーであるため、最初の方が高速になります。

于 2012-06-07T14:13:17.317 に答える