わさっきhb

大学(教育研究)とか ,親馬鹿とか,和歌山とか,とか,とか.

[C]多次元配列にアクセスする3つの方法: 検証コード

[C]多次元配列にアクセスする3つの方法 - わさっき
について,変数宣言が可能であることと,それぞれのサイズを確認するコードを書いてみました.
手元の処理系では,intとポインタのサイズが同じなので,区別するため,Tという型を作り,その2次元配列を参照するようにしました.

#include <stdio.h>

#define printf_d(x) (printf(#x " = %d\n", x))

typedef struct T_dummy {
  char A[123];
} T;

int main(void)
{
  /* 2次元配列 */
  T a[2][2];

  /* 配列のポインタ */
  T (*b_1)[2] = a;

  /* ポインタの配列 */
  T *b_2[2] = {a[0], a[1]};

  /* 1次元配列 */
  T *b_3_1 = &a[0][0];
  T *b_3_2 = a[0];
  T *b_3_3 = (T *)a;

  printf_d(sizeof(T));
  printf_d(sizeof(void *));

  printf_d(sizeof(b_1));
  printf_d(sizeof(b_1[0]));
  printf_d(sizeof(b_1[0][0]));

  printf_d(sizeof(b_2));
  printf_d(sizeof(b_2[0]));
  printf_d(sizeof(b_2[0][0]));

  printf_d(sizeof(b_3_1));
  printf_d(sizeof(b_3_1[0]));
  printf_d(sizeof(b_3_2));
  printf_d(sizeof(b_3_2[0]));
  printf_d(sizeof(b_3_3));
  printf_d(sizeof(b_3_3[0]));

  return 0;
}

実行結果は以下の通り.

sizeof(T) = 123
sizeof(void *) = 4
sizeof(b_1) = 4
sizeof(b_1[0]) = 246
sizeof(b_1[0][0]) = 123
sizeof(b_2) = 8
sizeof(b_2[0]) = 4
sizeof(b_2[0][0]) = 123
sizeof(b_3_1) = 4
sizeof(b_3_1[0]) = 123
sizeof(b_3_2) = 4
sizeof(b_3_2[0]) = 123
sizeof(b_3_3) = 4
sizeof(b_3_3[0]) = 123

前に作った表と合致します.「sizeof(b_1[0]) = 246」は,b_1[0]がT[2]型(配列型)であることを裏付けています.

2次元配列で連想するもの: ザナドゥのタワー

プログラムを実行するだけではつまらないので,昔話を.
ザナドゥというテレビゲームがあって,その中のタワーの部屋は,8×8の2次元配列で表現できる構造になっていました.
部屋の上下左右に,通路があれば,移動できるのですが,そこで注意するのは,2次元配列で考えたときの右端,つまり座標でいうと(7,y)のときに(0オリジンとします),右に移動すると,(0,y)ではなく(0,y+1)の部屋に移っていたということです.
2次元配列での上端・下端をまたぐ移動については,特にこのようなずれがなかったことから,タワーの部屋は,計算機内部では要素数64の1次元配列で構成されていて,移動前の部屋位置をi,移動後をi_afterとすると,

  • i_after = (i + delta) & 0x3f;

という代入で表現でき,ここの delta は,上下左右の移動に対してそれぞれ-8,8,-1,1,になっていたんだろうなと推測します.