まず、「影響」は、最初の方法が壊れていることです。int **
ポインターでは機能しません。
最初の方法で 2D 配列を 1 回で割り当てるには、実際には十分なサイズの 1D 配列を割り当てる必要があります。
int *arr = malloc( row * column * sizeof *arr );
// Note: `int *`, not `int **`
arr[i][j]
たとえば、する必要があるのではなく、手動でインデックスを再計算してアクセスを実行しますarr[i * column + j]
。
割り当てられたポインターを格納してからint **arr
配列にアクセスしようとすると、arr[i][j]
単にクラッシュするだけです。
次に、2 番目の方法で問題ありません。malloc
2 番目の方法では、複数の独立した呼び出しによって第 2 レベルのメモリを割り当てる必要がないというだけです。2 番目のレベルのメモリ全体を 1 回で割り当てることができます
int **arr = malloc( row * sizeof *arr );
int *arr_data = malloc( row * column * sizeof *arr_data );
次に、事前に割り当てられた第2レベルのメモリを行間で分配します
for (i = 0; i < row; i++)
arr[i] = arr_data + i * column;
(もちろん、必要に応じて、行を個別に割り当てることもできます。それも機能します。以下でコメントするように、最初のアプローチと 2 番目のアプローチの類似性をよりよく説明するために、それらを一度に割り当てたかったのです。)
さて、これら 2 つのメソッドを見ると、どちらも本質的に同じことを行うことが簡単にわかります。arr + i * column
唯一の違いは、最初の方法では、毎回計算することでその場で行の先頭を見つけることです(arr[i * column + j]
は と同等であることに注意してください(arr + i * column)[j]
)。2 番目の方法では、同じ数式を使用してすべての行の開始点を事前に計算し、arr_data + i * column
後で使用するために別の「行インデックス」配列に格納しarr
ます。
したがって、基本的には、メモリ使用量 (最初の方法では必要なメモリが少なくて済みます) と速度 (2 番目の方法の方が高速である可能性がありますが、必ずしもそうではありません) の間のトレードオフになります。同時に、2 番目の方法は 2D 配列アクセスの「自然な」構文をサポートしますarr[i][j]
が、最初の方法では、インデックスの再計算を伴うより複雑な 1D アクセス構文を使用する必要があります。