• ベストアンサー

2次元配列の動的確保&配列の添え字の書式について

(1)2次元配列の動的確保について 1次元配列の動的確保は理解できたのですが、次のプログラムの 文(ⅰ)~(ⅱ)の意味を理解できていないので教えてください。 int **a, j, k, nrows=3, ncolumns=4 ; a = (int **)malloc(nrows * sizeof(int *)); a[0] = (int *)malloc(nrows * ncolumns * sizeof(int)); …(ⅰ) //先頭アドレスに… for(j = 1; j < nrows; j++) a[j] = a[0] + j * ncolumns; …(ⅱ)   //この行が特にわかりません。 (2)配列の添え字について この書き方はどういう意味になりますか? out[X_SIZE * (i) + (j)] 分かる方、回答お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • bnosuke-x
  • ベストアンサー率39% (43/110)
回答No.2

(1)について 二次元配列のように見えて、実のところポインタの1次元配列を使って2次元配列のようにソース上で書き表す方法と思われます。 a = (int **)malloc(nrows * sizeof(int *))で、 intのポインタを入れる領域を行の分(3つ)準備し、その領域の先頭ポインタを a に入れます。 これで int *a[3]; としたのと同じものができました。 次に (int *)malloc(nrows * ncolumns * sizeof(int)) で、 [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11] の様に int の領域を取ります。 これは1次元配列と同じなのですが、 [ 0][ 1][ 2][ 3] [ 4][ 5][ 6][ 7] [ 8][ 9][10][11] の様に2次元配列に見立てて、 for(j = 1; j < nrows; j++)   a[j] = a[0] + j * ncolumns; …() で0,4,8を指すポインタをa[0],a[1]、a[2]に入れます。 (a[0]はすでに入っていますけどね) すると、 a[1][2]で[6]の場所を、 a[0][3]で[3]の場所を指すことができます。 なぜこうなるのかはK&Rにバッチリ書いてあるので、調べてください。 必要であれば、明日追加の解説を書きます。 (2)について 1次元配列を2次元配列のように使う書き方です。 out[n][X_SIZE]; の様に宣言した配列を、 out[i][j]のようにアクセスするのと同じ効果があります。 もちろん、i<n,j<X_SIZEの範囲です。 これを応用すると、1次元配列を何次元のものにも見立てることができます。 その逆も可能です。

ume-kun
質問者

お礼

回答を頂きありがとうございます。 この解説なら納得です! ありがとうございました。またよろしくお願いします!

その他の回答 (2)

  • bnosuke-x
  • ベストアンサー率39% (43/110)
回答No.3

ちょっと間違えました。 該当部分を以下のように差し替えてください。 -------ここから下全部-------- 次に malloc(nrows * ncolumns * sizeof(int)) で、 [ 0][ 1][ 2][ 3][ 4][ 5][ 6][ 7][ 8][ 9][10][11] の様に int の領域を取ります。 これは1次元配列と同じなのですが、 [ 0][ 1][ 2][ 3] [ 4][ 5][ 6][ 7] [ 8][ 9][10][11] の様に2次元配列に見立てて、 a[0]=(int *)malloc(nrows * ncolumns * sizeof(int)) for(j = 1; j < nrows; j++)   a[j] = a[0] + j * ncolumns; で0,4,8を指すポインタをa[0],a[1]、a[2]に入れます。

noname#22058
noname#22058
回答No.1

まず、(i)の上にある行で、行数(=3)分のポインタ領域を指す ポインタ a の領域を確保します。 次に(i)で、int型3行4列分全体の領域を指すポインタを a[0] に 格納します。イメージとしては、縦方向に3個、横方向に4個、 計12個の長方形を思い浮かべるとよいでしょう。 行番号、列番号とも、ここではゼロ始まりです。 つまり、0行0列~2行3列の12個です。 次のforループでは、1行目と2行目分の領域を指すポインタである a[1] と a[2] を設定しています。 a[1] は a[0] から横方向の数である4個分だけ ずれることになりますので、j(このときは1) * ncolums(=4) を加えています。 a[2] は a[1] からさらに4個分だけずれます。 a[0] からは8個分ずれますので、j(このときは2) * ncolumns を加えています。 out[X_SIZE * i + j] は、out[X_SIZE]を基点として、i行j列分だけ離れた領域のことです。

ume-kun
質問者

お礼

回答を頂きありがとうございます。 out[X_SIZE * i + j]で2次元配列の働きをするのですね!

関連するQ&A