関数の引数として n>1 の n 次元配列を指定する場合、配列全体の内容がコピーされるのか、それとも最初の要素のアドレスへのポインターだけなのか、興味があります。
関数のシグネチャが次のようなものであると仮定します。
int someFunction(int n, int arr[n][n]);
これは、あまり知られていない C99 拡張機能です。配列はこれまでと同様に参照によって渡されますが、コンパイラは可変長配列を処理するのと同様の方法で配列として解釈できます。
もちろん、これでは境界チェックは行われません。Cにはそれがない。
関数の署名では、
int someFunction(int n, int arr[n][n]);
最終的n
には何も得られず、無視されるだけです。でも新品int arr[n][]
です。それがC89になかったものです。以前は、唯一のオプションは、ベース ポインターから手動でインデックスを計算することでした。arr[n*x+y]
Ansi-C (C89) では、関数を次のように宣言する必要があります。
int someFunction(int n, int arr[]);
これはと同等です
int someFunction(int n, int *arr);
2 つのディメンションを 1 つのインデックスとして計算します。
新しい C99 マジックは、オリジナルを次のように縮小します。
int someFunction(int n, int *arr[n]);
このプロセスは、合格というよりもアレイの採用として説明したいと思います。配列をポインターとして渡すという最初の決定によって発生した損失の一部を軽減するだけです。
2 番目の 2 つの例は、一種の内部化された等価物であることを理解することが重要です。比喩的なイラスト。最後の配列では、配列はポインターの配列に変換されませんが、最小次元の境界は削除されます。おそらく、次のように説明したほうがよいでしょう。
int someFunction(int n, int arr[n][]);
配列を関数の引数としてコピーする唯一の方法は、それを構造体でラップすることです。ただし、可変次元を持つことはできません。
struct arr {int n; int arr[n][n];}; //Nope, won't compile!
enum { n = 3 };
struct arr { int arr[n][n]; };
struct arr someFunction( struct arr ); //argument and return value are copied.
そしてこれは1989年から合法化されています。
関数シグネチャの配列は一定の次元 (最終次元以外) を持たなければならないため、これは関数の不正なシグネチャです。
配列が関数パラメーターとして一定のサイズでなければならない理由は、それらが関数呼び出しで実際にコピーされないためです。ポインターのみが渡されます。