ある画像を読み込むため、その画像を格納できる幅、高さを持った配列を動的に確保しようと考えています。
幅を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件)
- 最新から表示
- 回答順に表示
No.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次元配列のようにアクセスしたいのでしょうか?
もしコードが簡単になるとか見やすくなるとか思っているのでしたら、それは勘違いです。
他人や一ヵ月後の自分は、ダブルポインタを使ったデータ構造を見て、難しいプログラムだと感じるでしょう。
あまり技巧に凝ったコードはシンプルに書かれたコードに比べて読みづらいものです。
し・か・し、
このように技巧に凝っていろいろ試行錯誤を繰り返す事は、自分の経験値アップに大いに役立ちます。
人に見せたり後世に残す必要の無いプログラムであれば、どんどん試してください。
No.2
- 回答日時:
根本的には
C言語の多次元配列をよく理解されていないために生じる思い違いですな。
結構、こういう方は多いですね。
実はC言語の多次元配列は、他の言語と大きく異なります
ひとことで表現すると、それは
「C言語の配列は、ツリー構造を成している」
ということです。
手持ち無沙汰な時に、この表現を呪文みたいに唱えて
よく考えてみましょう。
他の言語の多次元配列は、連続した領域をコンパイラーのほうで読み込みマクロを作ってくれているようなものなので、このようなC言語のような
気苦労はありませんわ。
No.1
- 回答日時:
★アドバイス
・過去に同じような質問に回答しました。
ので下のリンクを参考に。
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
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語 共用体について コマンドライン引数で値を2つ入力したときに、argv[2]の値をUNI u1 4 2022/04/25 20:34
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列を使わずに、変数名を動的...
-
C言語 配列の長さの上限
-
複数の選択範囲の行番号を個別...
-
配列で格納したものをmsgboxで...
-
メモリの初期値
-
配列同士の文字列の比較
-
VB.netでRadioButtonを配列にし...
-
パイソンの
-
2次元配列を戻り値とする関数?
-
FORTRAN77の配列(除算)
-
C# Listを使わずに2次元配列の...
-
ポインタの配列のコンマについて
-
unsigned char配列への入力の仕方
-
VBで構造体の配列を関数に渡す...
-
テキストファイルから文字列を...
-
C# 配列の変数宣言について。
-
テンキーの配列について
-
c++によるジャンケンプログラム
-
Functionの戻り値を2次元配列...
-
char型の配列 char buff[20] = ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列の参照渡しで型が一致しま...
-
配列を使わずに、変数名を動的...
-
VBで構造体の配列を関数に渡す...
-
配列で格納したものをmsgboxで...
-
unsigned char配列への入力の仕方
-
C# Listを使わずに2次元配列の...
-
C# 配列の変数宣言について。
-
擬似コード 長さがmの配列でな...
-
【速いブラインドタッチ】手を...
-
パイソンの
-
C言語初心者 ポインタについて...
-
ExcelVBAで質問です。離れた二...
-
配列を含む構造体の初期値について
-
複数の選択範囲の行番号を個別...
-
Functionの戻り値を2次元配列...
-
C++ vectorに配列をプッシュしたい
-
先頭アドレスとは何ですか?
-
テキストファイルから文字列を...
-
Redimした動的配列はEraseする...
おすすめ情報