Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

ファイルを構造体に読み こませたい

160 views
Skip to first unread message

Naoto Ikegaya

unread,
Sep 30, 2002, 10:08:30 AM9/30/02
to
はじめまして、池谷と申します。

.bmpファイルを読み込む処理を作っています。

struct BITMAPFILEHEADER {
char bfType[2];
unsigned int bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned int bfOffBits;
};

BITMAPFILEHEADER *pBfh =
(BITMAPFILEHEADER *)malloc(sizeof(BITMAPFILEHEADER));
fread(pBfh,sizeof(BITMAPFILEHEADER),1,fbmp)

として、ヘッダーを読み込みたかったのですが、bfTypeの後に2バイト余分にメ
モリが取られてしまっている為正しく読み込めません。
14バイト読みたいのですが、sizeof(BITMAPFILEHEADER)は16バイトになります。

初めはwindows.hをインクルードしていたのですが、途中から標準ライブラリだ
けで作ってみたくなって、外してしまいました。外す前は思い通りに読み込んで
いたので、何か構造体のメモリの取り方にオプションの設定があのでしょうか?
よろしくお願いします。

--
池谷 直人 <a_i...@mtf.biglobe.ne.jp>

T.T

unread,
Sep 30, 2002, 10:29:03 AM9/30/02
to
(T.T)です。

Naoto Ikegaya <a_i...@mtf.biglobe.ne.jp> wrote:
> struct BITMAPFILEHEADER {
> char bfType[2];
> unsigned int bfSize;
> unsigned short bfReserved1;
> unsigned short bfReserved2;
> unsigned int bfOffBits;
> };
>
> BITMAPFILEHEADER *pBfh =
> (BITMAPFILEHEADER *)malloc(sizeof(BITMAPFILEHEADER));
> fread(pBfh,sizeof(BITMAPFILEHEADER),1,fbmp)
>
> として、ヘッダーを読み込みたかったのですが、bfTypeの後に2バイト余分にメ
> モリが取られてしまっている為正しく読み込めません。


構造体を宣言する前に

#pragma pack(1)

したら大丈夫かと思います。

http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclang/html/_predir_pack.asp
のあたりも参考に。


---
加藤 明(大阪大学文学部音楽学専修4年)
mail : turu...@mint.freemail.ne.jp
web : http://blue.sakura.ne.jp/~turugina/

IIJIMA Hiromitsu

unread,
Sep 30, 2002, 10:42:12 AM9/30/02
to
いいじまです。

お使いのコンパイラが書いていませんが、Visual C++ や Borland C++ なら、

#pragma pack(1)

としてください。GCC もこれでよさそうですが、他のコンパイラは不明。
詳細はコンパイラのヘルプを参照してください。

余談

細かいことですが、int や short のサイズもコンパイラ依存なので、
コンパイラ非依存にしたければ、int、short、char よりは、
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD; // long が 64bit の処理系は無視(^^;)
と定義して、BYTE、WORD、DWORD で表記するほうがいいと思います。

#C99 の stdint.h を使うっていう手もあるけど、まともにサポートしている
#処理系が少ない…

========================================================================
飯嶋 浩光 / でるもんた・いいじま http://www.ht.sakura.ne.jp/~delmonta/
IIJIMA Hiromitsu, aka Delmonta [PC] mailto:delm...@ht.sakura.ne.jp

MIYAZAKI Shin

unread,
Sep 30, 2002, 10:57:52 AM9/30/02
to
<2002093022434...@mtf.biglobe.ne.jp> の記事において
Naoto Ikegaya <a_i...@mtf.biglobe.ne.jp> が書いたことについて、

> 初めはwindows.hをインクルードしていたのですが、途中から標準ライブラリだ
> けで作ってみたくなって、外してしまいました。

まずそんなことをしない。

--
みやざき
sh...@miyazaki.email.ne.jp

Naoto Ikegaya

unread,
Sep 30, 2002, 11:44:05 AM9/30/02
to
皆さんすばやいフォローありがとうございます。

> 構造体を宣言する前に
>
> #pragma pack(1)
>
> したら大丈夫かと思います。
>
> http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclang/html/_predir_pack.asp
> のあたりも参考に。

(T.T)さんありがとうございます。ドキュメントも参考になりました。

> 細かいことですが、int や short のサイズもコンパイラ依存なので、
> コンパイラ非依存にしたければ、int、short、char よりは、
> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD; // long が 64bit の処理系は無視(^^;)
> と定義して、BYTE、WORD、DWORD で表記するほうがいいと思います。

飯島さんありがとうございます。そうします。

> まずそんなことをしない。
宮崎さん、おっしゃるとおりです。でも、悩んだおかげで勉強になりました。

--
池谷 直人 <a_i...@mtf.biglobe.ne.jp>

Iwao Watanabe

unread,
Sep 30, 2002, 7:43:09 PM9/30/02
to
"Naoto Ikegaya" <a_i...@mtf.biglobe.ne.jp> wrote
in message news:2002093022434...@mtf.biglobe.ne.jp...

>
> .bmpファイルを読み込む処理を作っています。
>
> struct BITMAPFILEHEADER {
> char bfType[2];
> unsigned int bfSize;
> unsigned short bfReserved1;
> unsigned short bfReserved2;
> unsigned int bfOffBits;
> };
>
> BITMAPFILEHEADER *pBfh =
> (BITMAPFILEHEADER *)malloc(sizeof(BITMAPFILEHEADER));
> fread(pBfh,sizeof(BITMAPFILEHEADER),1,fbmp)
>
> として、ヘッダーを読み込みたかったのですが、bfTypeの後に2バイト余分にメ
> モリが取られてしまっている為正しく読み込めません。
(snip)

構造体のメンバの隙間の存在を
よく理解できていないときにやってしまうミスですね。
Windows以外のwindows.hがない処理系でも同じソースを使いたいときには、
たとえば次のように記述します。

char buf[14];
BITMAPFILEHEADER hb, *p = &hb;

fread(buf,1,sizeof buf,fp);

p->bfType[0] = buf[0];
p->bfType[1] = buf[1];
p->bfSize = ((buf[5] & 255ul) << 24) | ((buf[4] & 255ul) << 16) |
((buf[3] & 255) << 8) | (buf[2] & 255)
p->bfOffBits = ((buf[13] & 255ul) << 24) | ((buf[12] & 255ul) << 16) |
((buf[11] & 255) << 8) | (buf[10] & 255)

こんな感じで対応すると構造体のメンバの隙間は意識しなくてもよくなります。

ところで上の例では展開していますが、
実際にはcharを組み立てて、int に代入できるように変換している部分は
マクロ定義等で対処したほうがコードがすっきりしてよいと思います。

#define get_int(buf) ((3[buf] & 255ul) << 24) | ((2[buf] & 255ul) << 16) | \
((1[buf] & 255) << 8) | (0[buf] & 255)

p->bfSize = get_int(buf + 2);
p->bfOffBits = get_int(buf + 10);

どうですか?

Hoshi Takanori

unread,
Sep 30, 2002, 10:21:07 PM9/30/02
to
ほしです。

In article <2002093022434...@mtf.biglobe.ne.jp>
Naoto Ikegaya <a_i...@mtf.biglobe.ne.jp> writes:

> 初めはwindows.hをインクルードしていたのですが、途中から標準ライブラリだ
> けで作ってみたくなって、外してしまいました。

「標準ライブラリだけで作る」というのが「特定のプラット
フォームに依存しないように作る」ということならば、
#pragma pack を使ったり、int や short int のサイズや
byte order に勝手な仮定をおいたり、構造体をそのまま
fread() で読み込んだりもすべきではないと思います。

そうでないなら、「標準ライブラリしか使ってないけど、
特定のプラットフォームでしか動かない」ということになり
ますが、それに何の意味があるのかはちょっと疑問です。

ほし

Naoto Ikegaya

unread,
Sep 30, 2002, 11:34:43 PM9/30/02
to
こん○○は 池谷です。

On 01 Oct 2002 02:21:07 GMT
ho...@sra.co.jp (Hoshi Takanori) wrote:

> 「標準ライブラリだけで作る」というのが「特定のプラット
> フォームに依存しないように作る」ということならば、
> #pragma pack を使ったり、int や short int のサイズや
> byte order に勝手な仮定をおいたり、構造体をそのまま
> fread() で読み込んだりもすべきではないと思います。

ありがとうございます。目からうろこです。Σ(;o;) そうなんです。あとで
Linuxとかでも動かしてみたいと思ってました。それで環境に依存しないように
作るにはIwaoさんの方法でやればいいんですね。勉強になりました。

IIJIMA Hiromitsu

unread,
Oct 1, 2002, 2:14:30 AM10/1/02
to
いいじまです。

> 「標準ライブラリだけで作る」というのが「特定のプラット
> フォームに依存しないように作る」ということならば、
> #pragma pack を使ったり、int や short int のサイズや
> byte order に勝手な仮定をおいたり、

そうでした。byte order のことをすっかり忘れていました。
#標準ライブラリではないですが htonl() をこまめに使えば byte order の
#問題はほぼ解決します。ただ、.bmp ファイルはリトルエンディアンだから、
#この場合には解決にならない。

というわけで、一般論として

> 構造体をそのままfread() で読み込んだりもすべきではない

ということになりますね。

int/short のサイズの問題については、C99 の stdint.h を使うか、
それもどきを自作するかすれば何とかなりますけど。

tabe

unread,
Oct 2, 2002, 9:24:09 AM10/2/02
to

田部です。

"IIJIMA Hiromitsu" <delm...@ht.sakura.ne.jp> wrote in message
news:3D9862C4...@ht.sakura.ne.jp...
> いいじまです。


> 細かいことですが、int や short のサイズもコンパイラ依存なので、
> コンパイラ非依存にしたければ、int、short、char よりは、
> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD; // long が 64bit の処理系は無視(^^;)
> と定義して、BYTE、WORD、DWORD で表記するほうがいいと思います。

私の考えは少し違うのでコメント(疑問)します。
尚、Windowsで一生、飯を食っていくのであれば、
いいじまさんの言っている事は、
「郷にいれば郷に従え」で何の反論、異議はありません。

疑問1:符号付きはどう書くの?


> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD;

で、符号無しの場合は、こう書くとして、
符号無しはどう書くの?
符号無しの場合が、
DWORDで、
符号有りの場合は???
signed long
って書くの?
#なんか、大文字と小文字の使い分けとか、
#美意識、反意語の感覚が
#ズタズタ。

疑問2:それは、符号付き?符号無し?、何バイト?何bit?


> typedef unsigned char BYTE;
> typedef unsigned short WORD;
> typedef unsigned long DWORD;

上記の、typedefは通常、.c ではくて、.h に記述されます。
Windowsの場合は、処理系が提供するヘッダファイル内で
記述しています。
が、
通常市販の書籍では、
BYTEとは、C言語で何である
WORDとは、C言語で何である
DWORDとは、C言語で何である
とは、説明されていません。
#だって、処理系(が提供したtypedef)依存だもん。
この様な、BYTE,WORD、DWORDをプロジェクトに導入して
新人が理解できるのだろか?
と言うのが疑問です。

#導入した人は、神様のつもりでも、
#民がついて来てるか????
#WORDの単語の中には、
#符号付き、符号無しの情報が何もない。
#bit数の情報もない。

例:
typedef unsigned short WORD :
WORD func(WORD arg)
{
if(arg == -1) {
return -1 ;
}
return 0 ;
} /* こんなコード記述してない?あなた? */

まとめ、
1) BYTE,WORD、DWORDを非Windows系に導入する前に、
UNIX系ならば、
%man limits ↓
の使用方法を学習すべきです。
2)本当に処理系に依存したくないのであれば、
http://www.catnet.ne.jp/kouno/c_faq/c2.html#12
を、読む事
厳しい。。。。
--
以上
見て、勝手使って http://rec.ncos.co.jp

Shinji KONO

unread,
Oct 2, 2002, 11:11:27 AM10/2/02
to
河野 真治@琉球大情報工学です。

In article <aneseo$s8q$1...@bgsv5906.tk.mesh.ad.jp>, "tabe" <ta...@mug.biglobe.ne.jp> writes


>尚、Windowsで一生、飯を食っていくのであれば、
>いいじまさんの言っている事は、
>「郷にいれば郷に従え」で何の反論、異議はありません。
>疑問1:符号付きはどう書くの?
>> typedef unsigned char BYTE;

そりゃもう、ハンガリアンノーテーションの世界でしょう。

---
Shinji KONO @ Information Engineering, University of the Ryukyus,
PRESTO, Japan Science and Technology Corporation
河野真治 @ 琉球大学工学部情報工学科,
科学技術振興事業団さきがけ研究21(機能と構成)

IIJIMA Hiromitsu

unread,
Oct 2, 2002, 1:35:58 PM10/2/02
to
いいじまです。

> > コンパイラ非依存にしたければ、int、short、char よりは、
> > typedef unsigned char BYTE;
> > typedef unsigned short WORD;
> > typedef unsigned long DWORD; // long が 64bit の処理系は無視(^^;)
> > と定義して、BYTE、WORD、DWORD で表記するほうがいいと思います。
>
> 私の考えは少し違うのでコメント(疑問)します。
> 尚、Windowsで一生、飯を食っていくのであれば、
> いいじまさんの言っている事は、
> 「郷にいれば郷に従え」で何の反論、異議はありません。

はい(^^;)

> 疑問1:符号付きはどう書くの?
> > typedef unsigned char BYTE;
> > typedef unsigned short WORD;
> > typedef unsigned long DWORD;
> で、符号無しの場合は、こう書くとして、
> 符号無しはどう書くの?
> 符号無しの場合が、
> DWORDで、
> 符号有りの場合は???
> signed long
> って書くの?

もともと BYTE、WORD、DWORD ってのは x86 アセンブラの用語をその
まま C 言語に持ち込んだって感じですので、符号の有無は意識して
いないことが多いですね。符号を意識するなら signed long にキャ
ストして、と。

わたしなら、まともに書くときは C99 の stdint.h を真似るために、
まず
#include<limits.h>
として、
#if UINT_MAX==0xFFFFFFFFUL
typedef unsigned int uint32_t;
#elif USHORT_MAX==0xFFFFFFFFL //short=32bit,int=64bit???
typedef unsigned short uint32_t;
#elif ULONG_MAX==0xFFFFFFFFL
typedef unsigned long uint32_t;
#else
#error Do you have 32-bit data type?
#endif
とか、
#if LONG_MAX==0x7FFFFFFFFFFFFFFFFL
typedef long int64_t;
#elif defined(LLONG_MAX) && LLONG_MAX==0x7FFFFFFFFFFFFFFFFLL
typedef long long int64_t;
#elif defined(_I64_MAX)
typedef __int64 int64_t;
#endif
とかを自作ヘッダに書きます。stdint.h がまだ存在しない処理系は多い
(FreeBSD 4.4、VC4.0、BCC 5.5.1 は全滅)ので。

以下半分ゴミ

> 1) BYTE,WORD、DWORDを非Windows系に導入する前に、
> UNIX系ならば、
> %man limits ↓
> の使用方法を学習すべきです。

FreeBSD 4.4 で man limits したら全然関係ないものが出てきました :-)

> 2)本当に処理系に依存したくないのであれば、
> http://www.catnet.ne.jp/kouno/c_faq/c2.html#12
> を、読む事
> 厳しい。。。。

これは同感。char 型の配列に読み込んで、そこから手作業で解析ですね。
最適化はコンパイラに任せる、と。

Kazuo Fox Dohzono

unread,
Oct 3, 2002, 5:05:08 AM10/3/02
to
In article <3D9B2E7E...@ht.sakura.ne.jp>
IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> writes:

> FreeBSD 4.4 で man limits したら全然関係ないものが出てきました :-)

FreeBSD だと

$ man 3 stdio

ってのはあるみたいですね. ヘッダだけの話じゃないけど.

--
Kazuo Fox Dohzono / doh...@hf.rim.or.jp

Kazuo Fox Dohzono

unread,
Oct 3, 2002, 5:26:10 AM10/3/02
to
In article <3D993D46...@ht.sakura.ne.jp>
IIJIMA Hiromitsu <delm...@ht.sakura.ne.jp> writes:

> #標準ライブラリではないですが htonl() をこまめに使えば byte order の
> #問題はほぼ解決します。

私の場合バイトオーダ問題を扱う部分は用途が明確になるようメモリを指定す
るようにしています.

unsigned bget2 (const unsigned char *p);
unsigned long bget4 (const unsigned char *p);
void bset2 (unsigned char *p, unsigned v);
void bset4 (unsigned char *p, unsigned long v);

0 new messages