プロが教えるわが家の防犯対策術!

ある画像を読み込むため、その画像を格納できる幅、高さを持った配列を動的に確保しようと考えています。
幅をxsize、高さをysizeで次のように記述しました。

unsigned char **src;
int i;
src = (unsigned char**)malloc(sizeof(unsigned char*) * ysize);
src[0] = (unsigned char*)malloc(sizeof(unsigned char) * xsize * ysize);
for(i=1; i<ysize; i++)
src[i] = (src[0] + i * xsize);

わざわざポインタのポインタを使用したのは、動的に確保した配列を2次元的なアクセスをしたかったためです。

画像の読み込み時は

fread(src[0], sizeof(unsigned char), xsize * ysize, fp);

としています。
上に記述したソースは問題なく動作しました。
しかし、上の場合だと全ての配列を連続して確保することができません。つまりsrcでmallocを一回、src[0]でmallocを一回使っているため、ポインタの配列の直後に配列を確保する保障がありません。そこでいっぺんに確保することを考えました。


unsigned char **src;
int i;

src = (unsigned char **)malloc(sizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize);

for(i=0; i<ysize; i++)
src[i] = (unsigned char *)(src + sizeof(unsigned char *) * ysize + i * xsize);

このように組み上げ、読み込み時は上のfreadと同様に記述したところエラーが出てしまいました。

やはり一行目のmallocで無理やりsizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize分確保するのは失敗だったのでしょうか?

A 回答 (3件)

2次元配列のアドレスをセットする


 
 src[i] = (unsigned char *)(src + sizeof(unsigned char *) * ysize + i * xsize);
 
の最後の i * xsize が原因ではないでしょうか。
ポインタ変数は4バイトなので、ポインタのポインタであるsrcに例えば src + 1 などとするとアドレスに4が加算されてしまいます。
i * xsize を足したつもりが、その4倍の値が足されている訳です。
ためしに、上記コードの直後に
 
 for(i = 0; i < ysize; i++){ printf("%d\n", src[i]); }
 
などとして、ポインタが指すアドレスを確かめてみて下さい。
以下のように書き換えると正しく動作すると思います。
 
 src[0] = (unsigned char *)(src + sizeof(unsigned char *) * ysize);
 for(i = 1; i < ysize; i++)
 {
  src[i] = src[i-1] + xsize;
 }
 
 
ちなみに蛇足ですが、なぜ2次元配列のようにアクセスしたいのでしょうか?
もしコードが簡単になるとか見やすくなるとか思っているのでしたら、それは勘違いです。
他人や一ヵ月後の自分は、ダブルポインタを使ったデータ構造を見て、難しいプログラムだと感じるでしょう。
あまり技巧に凝ったコードはシンプルに書かれたコードに比べて読みづらいものです。
 
し・か・し、
このように技巧に凝っていろいろ試行錯誤を繰り返す事は、自分の経験値アップに大いに役立ちます。
人に見せたり後世に残す必要の無いプログラムであれば、どんどん試してください。
 
    • good
    • 0

根本的には


C言語の多次元配列をよく理解されていないために生じる思い違いですな。
結構、こういう方は多いですね。

実はC言語の多次元配列は、他の言語と大きく異なります
ひとことで表現すると、それは
「C言語の配列は、ツリー構造を成している」
ということです。
手持ち無沙汰な時に、この表現を呪文みたいに唱えて
よく考えてみましょう。

他の言語の多次元配列は、連続した領域をコンパイラーのほうで読み込みマクロを作ってくれているようなものなので、このようなC言語のような
気苦労はありませんわ。
    • good
    • 0

★アドバイス


・過去に同じような質問に回答しました。
 ので下のリンクを参考に。
 http://oshiete1.goo.ne.jp/qa3022605.html→『callocで二次元配列を作成するには?』
 ↑http://oshiete1.goo.ne.jp/qa2619388.html→『3次元配列でのポインタ 』
 |
 これを参考にして下さい。回答 No.1 の方です。
・以上。

参考URL:http://oshiete1.goo.ne.jp/qa3022605.html
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!