1. ホーム
  2. c

[解決済み】多次元配列はメモリ上でどのようにフォーマットされるのですか?

2022-04-18 02:24:45

質問

C言語では、次のコードを使用して、ヒープ上に2次元配列を動的に割り当てることができますね。

int** someNumbers = malloc(arrayRows*sizeof(int*));

for (i = 0; i < arrayRows; i++) {
    someNumbers[i] = malloc(arrayColumns*sizeof(int));
}

明らかに、これは実際に整数の束の別々の一次元配列へのポインタの一次元配列を作成し、"The System"は私が求めるときに何を意味するかを把握することができます。

someNumbers[4][2];

しかし、次の行のように2次元配列を静的に宣言すると......。

int someNumbers[ARRAY_ROWS][ARRAY_COLUMNS];

...同様の構造がスタック上に作成されるのでしょうか、それとも完全に別の形式なのでしょうか?(すなわち、それはポインタの1次元配列ですか?そうでない場合、それは何ですか、そして、それへの参照はどのように把握されますか?)

また、私が「システム」と言った場合、実際にそれを把握するのは何なのでしょうか?カーネルですか?それとも、Cコンパイラがコンパイル時に整理しているのでしょうか?

解決方法は?

静的2次元配列は、配列の配列のように見えますが、メモリ上に連続的に配置されています。 配列とポインタは同じものではありませんが、同じように使えることが多いので、時々混乱することがあります。 しかし、コンパイラは適切に追跡し、すべてをうまく並べてくれます。 静的な2次元配列には注意が必要です。 int ** というパラメータがあると、まずいことになります。 以下に簡単な例を示します。

int array1[3][2] = {{0, 1}, {2, 3}, {4, 5}};

メモリ内では以下のようになります。

0 1 2 3 4 5

まさに と同じです。

int array2[6] = { 0, 1, 2, 3, 4, 5 };

しかし、もし array1 をこの関数に渡してください。

void function1(int **a);

を実行すると、警告が表示されます (そして、アプリは配列への正しいアクセスに失敗します)。

warning: passing argument 1 of ‘function1’ from incompatible pointer type

2次元配列は int ** . 配列からポインタへの自動的な分解は、いわば一段深いところからしか行われないのです。 というように関数を宣言する必要があります。

void function2(int a[][2]);

または

void function2(int a[3][2]);

すべてを幸せにするために。

この同じコンセプトは、次のように拡張されます。 n -次元の配列です。 しかし、このようなおかしなことを利用すると、かえって分かりにくくなるのが一般的です。 だから、気をつけてね。