質問: 前提 -- BITMAPのファイルの読み書きをしようとしています。 書籍やgithubをながめていると、「ヘッダーのメンバ毎に変数を定義して読み込む方法」をよく見かけます。 ``` // メンバ毎に変数を定義し読み込む unsigned int bitmap_size; fread(&bitmap_size, 4, 1, fp); // 以降、メンバの数だけ似たような記述が増える ``` 課題 -- 上記の記述だとヘッダーの数だけ行数が増えていき、冗長に感じたので、事前に定義していた構造体のサイズ分メモリ空間を用意して一気に読み込もうとしました。 ``` BITMAPINFOHEADER bitmapInfoHeader; fread(&bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp); ``` ですが、構造体のメモリアラインメントのせいで~~`BITMAPINFOHEADER構造体`~~ `BITMAPFILEHEADER構造体`のサイズがメンバーサイズの合算値にならないため、期待したサイズよりも多く読み込んでいるようです。 この方法では読み込みだけでなく書き込みでも同様にパディング分ゴミが入ってしまいます。 追記:実際にはBITMAPFILEHEADERが14byteから16byteにアラインメントされてしまったため、BITMAPINFOHEADERの読み込みがずれてしまっていたようです。 上記の課題を避けるために`#progma pack`などでアラインメントの最適化をキャンセルすることができるとは思うのですが、いまいちこれがクリーンコーディングと言えるのか、大規模なOSS開発で是とされているのか、なにぶんC/C++での開発経験が乏しい私には判断がつきませんでした。 教えてほしいこと -------- 今回はC言語で書いていますが、モダンで大規模なOSSのC++プロジェクトだと前提を置いたとして BITMAPに限らず、ファイルの読み書きを行うときには多少冗長ながらも、最初に述べた「ヘッダーのメンバ毎に変数を定義して読み込む方法」が理想的(or よく使われる書き方)なのでしょうか? 他にも、C/C++で開発をしている方で美しい書き方を知っていればぜひ教えてください。
回答: こんにちは。 BITMAPINFOHEADERはアライメントは取れているので、通常はパディングは発生しないはずです。 > > 事前に定義していた構造体のサイズ分メモリ空間を用意して一気に読み込もうとしました。 > > > 私が見たことがあるサンプルは大抵この方法でリード/ライトしていますし、私自身もそのようにすることがあります。 もしかして、BITMAPFILEHEADERとBITMAPINFOHEADERをもつ構造体を定義して、そこへ読み込もうとするとおっしゃる問題が発生すると思います。 > > BITMAPに限らず、ファイルの読み書きを行うときには多少冗長ながらも、最初に述べた「ヘッダーのメンバ毎に変数を定義して読み込む方法」が理想的(or よく使われる書き方)なのでしょうか? > > > 個人的にはこれはバグを生みやすいので「無し」です。 C/C++では、データ交換についてはどうしてもCPUの特性を把握して処理系毎に専用のコードを書く必要がある場合が多いです。(特にエンディアン) アライメントもその一つと思います。msvcでは #progma pack を使うのは落とし所のように感じます。