C/C++ では、2 次元配列であっても、1 行ずつメモリに順次格納されます。したがって、(単一の関数で)次の場合:
int a[5][3];
int *head;
head = &a[0][0];
a[2][1] = 2; // <--
あなたが実際にアクセスしている要素a[2][1]
は*(head + 2*3 + 1)
、その要素が0
行の3つの要素、行の3つの要素1
、そしてさらにもう1つのインデックスの後にあります。
次のような関数を宣言すると:
void some_function(int array[][]) {...}
構文的には、エラーにはなりません。しかし、array[2][3]
今アクセスしようとすると、どの要素にアクセスする必要があるのか わかりません。一方、次の場合:
void some_function(int array[][5]) {...}
を使用すると、関数が 2 番目の次元のサイズを知っているためarray[2][3]
、メモリ アドレスの要素に実際にアクセスしていると判断できます。*(&array[0][0] + 2*5 + 3)
前に提案したように、次のような関数を宣言できます。
void some_function(int *array, int cols) { ... }
このようにして、前と同じ「情報」で関数を呼び出しているため、列の数です。次に、配列要素へのアクセス方法が少し異なり*(array + i*cols + j)
ます。通常は と書く場所にを書く必要がありますarray[i][j]
。原因array
は、(ポインターではなく) 整数へのポインターになりました。
このような関数を宣言するときは、使用されるだけでなく、配列に対して実際に宣言されている列の数で呼び出すように注意する必要があります。たとえば、次のようになります。
int main(){
int a[5][5];
int i, j;
for (i = 0; i < 3; ++i){
for (int j=0; j < 3; ++j){
scanf("%d", &a[i][j]);
}
}
some_function(&a[i][j], 5); // <- correct
some_function(&a[i][j], 3); // <- wrong
return 0;
}