2次元配列の動的確保 (C)

以前C++について書きましたが今回はCで。

#include <stdio.h>
#include <stdlib.h>

int main(void){
	int row = 4;
	int col = 7;
	int** arr;
	int i, j;
	// 領域の確保
	arr = (int**)calloc(row, sizeof(int));
	for (i=0; i<row; i++) {
		arr[i] = (int*)calloc(col, sizeof(int));
	}
	// アクセス
	for(i=0; i<row; i++){
		for(j=0; j<col; j++){
			arr[i][j] = i + j;
		}
	}
	for(i=0; i<row; i++){
		for(j=0; j<col; j++){
			printf("%d\t", arr[i][j]);
		}
		putchar('\n');
	}	
	// 解放
	for (i=0; i<row; i++) {
		free(arr[i]);
	}
	free(arr);
	return 0;
}

合ってるのかはわかりません。特にfreeが。

大昔受けた大学のプログラミング演習では、このようなメモリの動的確保やビットシフトなど結構肝心なところをスルーされてしまいました。非常に大事だと思うのですが。



上記の例は、多分メモリが連続になりません。連続にするには、多分こんな感じ??

#include <stdio.h>
#include <stdlib.h>

int main(void){
	int row = 4;
	int col = 7;
	int** arr;
	int* arr_base;
	int i, j;
	// 領域の確保
	arr = (int**)calloc(row, sizeof(int));
	arr_base = (int*)calloc(row * col, sizeof(int));
	// 各行の先頭が指すアドレスを設定
	for (i=0; i<row; i++) {
		arr[i] = &arr_base[i * col];
	}
	// アクセス
	for(i=0; i<row; i++){
		for(j=0; j<col; j++){
			arr[i][j] = i + j;
		}
	}
	for(i=0; i<row; i++){
		for(j=0; j<col; j++){
			printf("%d\t", arr[i][j]);
		}
		putchar('\n');
	}	
	// 解放
	free(arr);
	free(arr_base);
	return 0;
}

配列の領域自体はarr_baseという1次元配列でとっておき、arrはそれを一定の要素数ごとに行とみなすようポインタを入れておく感じです。


ただし、こんなことをするのは面倒なので、普通はここでいうarr_baseのような1次元配列を arr_base[i*row + j] のような感じでアクセスして2次元配列に見立てるようにすると思います。