B級科学者もどきの憂鬱

とある理系になりきれない奴のつれづれなる活動記

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

変なポインタ

C言語で、二次元配列を動的に確保するには
どうすればいいのかを調べてみました。
なるほど私もまだまだ甘いようだ。

なお、下にあるソースコードは、全角スペースを使っているため、
そのままコピーしてコンパイルすることはできません。
半角スペースに置換してください。
それと、メモリ確保できなかった場合のエラー処理も書いていません。
必ず追加してからコンパイルしてください。

ここでは例として、
double array[50][100]
と言う型を宣言します。

第一の方法
これが多分、最も基本的な方法。
他の初心者向けサイトでも、この方法を載せているところが多い。
ポインタの配列を確保して、そこにさらに二次元目の要素数分のメモリを確保する。

double **array;
size_t row,column;
int n;

row=50;    //一次元目の要素数
column=100;  //二次元目の要素数

array=(double**)malloc(sizeof(double*) * row);
for(n=0; n<row; n++)
    array[n]=(double*)malloc(sizeof(double) * column);

//何か処理

for(n=0; n<row; n++)
    free(array[n]);
free(array);

この方法には欠点がいくつかある。
まず、ポインタの配列を確保するためのメモリが余分に必要になる。
確保したメモリが連続していない可能性が高い。
メモリを確保するのにも開放するのにもループ処理が必要で、結構めんどくさい。

ただ、二次元目の要素数が異なる配列を容易に作ることが出来る。
例えばこういうデータを格納する場合は、この方法が一番無駄が無い。
data[0]="are?";
data[1]="koega":
data[2]="okurete";
data[3]="kikoetekuruzo?";


第二の方法
第一の方法を、メモリ領域を連続させるように改良したもの。

double **array;
size_t row,column;
int n;

row=50;    //一次元目の要素数
column=100;  //二次元目の要素数

array=(double**)malloc(sizeof(double*) * row);
array[0]=(double*)malloc(sizeof(double) * row * column);
for(n=1; n<row; n++)
    array[n]=array[0] + row * n;

//何か処理

free(array[0]);
free(array);

赤字が、第一の方法からの変更点。
開放も少し楽になる。
でも、余分なメモリが必要なことには変わりない。


第三の方法
一次元配列として確保する。

double *array;
size_t row,column;

row=50;    //一次元目の要素数
column=100;  //二次元目の要素数

array=(double*)malloc(sizeof(double) * row * column);

//何か処理

free(array);

この方法は、メモリ管理部分の記述が少なくて済む。
余分なメモリも使わない。
ただ、配列へのアクセスが少々めんどくさい。
例えば、array[25][75]にアクセスしたいなら、こう書く。
array[25 * row + 75]


第四の方法
二次元目の要素数があらかじめ決まっている場合のみ使える方法。

double (*array)[100];
size_t row,column;

row=50;    //一次元目の要素数
column=100;  //二次元目の要素数

array=(double(*)[100])malloc(sizeof(double) * row * column);

//何か処理

free(array);

double(*)[100]、こんな型、初めて見たw
配列へのアクセスも普通にできる。
メモリ確保も開放も簡単。
もちろんメモリ領域は連続している。


このことを調べたのは、C言語で複素数の計算をするために、
double value[][2];
という型を動的に確保して使いたかったためです。

わざわざ二次元配列にせずとも、実数部と虚数部を別々に、
double *re, *im;
と宣言しても出来るのですが、メモリアクセスの効率を考えると、
実数部と虚数部を隣同士の位置に置いておく方が速くなりますしね。

ちなみに、上の方法は全て、三以上の多次元配列にも適用できます。

さて、音声処理のプログラミングに戻るか。

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://scientistb.blog42.fc2.com/tb.php/28-3231e8bb
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

まとめ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。