【C言語】バイナリーデータ作成は明確な意思を持つべき

 普段は高レベルなプログラミングをしている人も、業務によっては低レベルなプログラムをすることもあります。近年ではXMLやJSONなどのテキストベースのデータ交換手法や、データベースエンジンへの書き込みでデータのやり取りをするので、そもそもの概念がない人もいます。


データ交換に明確な意思は必要

はるか昔ですが、C言語で整数型のデータをバイナリーデータとしてディスクに保管するサブシステムを作成しました。

仕様は先輩が作っていたのだが、そのときに整数型の順番は決まっているが、どのようにバイナリー化するかが決まっていませんでした。

ビッグエンディアンか?リトルエンディアンか?

気持ち悪いので先輩に聞き返したら。「それぞれ4バイトなのだから順番に入れれば良い」と言われました。それ以上の事は言いませんでした。当然リトルエンディアンなのかわかりません。

とりあえず、ビッグエンディアンとしてプログラムを作成しましたが、後で驚く発言を聞きました。

整数は上位下位が反転するのが常識です

これが、先輩の指示でした。まあ、ひどすぎです。確かにIntel系CPUだと、int型の整数をそのままメモリーダンプすれば、上位下位は逆転します。確かにそのとおりですが、なってしまうって指示は酷いです。

仕様を作るときは、決して「なってしまう」などという表現はしません。明確に行います。この場合なら

  • 整数は4バイトのリトルエンディアンで出力する
  • 実行される環境は全てWindowsでIntelのCPUである
  • 今回はビッグエンディアンの環境では実行されない
  • 今回はパフォーマンスを優先するため、ソフトウェアでの処理は見送る
  • 今回はSUNなどのビッグエンディアンの環境への移植性は考えない

というくらいの指示が必要です。

C言語での実験

#include<stdio.h>

//int型の動きを知るプログラム
main(){

unsigned char buf[10]; //とりあえず10バイト分のバッファを確保
int *iData; //整数型のポインタを宣言

//10バイト分のバッファを全て255で埋める
for(int i=0;i<10;i++){
buf[i]= 255;
}
//整数型のポインタのアドレスをバッファの先頭に設定する
iData = (int *)buf;
//整数型ポインタのアドレスに1000を代入
*iData = 1000;

//バッファの中身を表示
for(int i=0;i<10;i++){
printf("%d\n",buf[i]);

//本プログラムの狙いとしては、全てのバッファを埋めた後、同じアドレスに整数を代入する。
//バッファーが255で無い場合は、整数型の代入によって影響を受けたということになる。
//観察ポイントとしては、255じゃない部分の数が整数型のバイト数。
//数字が昇順であればintel系CPU,じゃなければ他のCPUということになる
//メモリーマッピングをする場合は、この方法は望ましくない。積極的に仕様を決めるべきである。
}
}

以上のコードを実験のために作りました。整数型の変数をメモリにダンプするとどうなるかの確認です。

仮に10バイトの領域を確保し255のデータで埋めます。次に、整数型のポインタを宣言し、そのアドレスを先程の10バイトの領域の先頭に設定します。

そして、その整数型のアドレスに1000を書き込みます。

これを私の環境 Windows11 で実行すると 先頭が232 次が3,次が0、次も0,そして後は255が続きます。

実行結果、最初の4バイトが整数として使われている

これが意味するところは

整数型を代入すると最初の4バイトに値が書き込まれる。先頭が232,次が3ということは収納はリトルエンディアンであるということです。

C言語でプログラムを組んでいる人は、常にこのような実験コードを動かして、ハードウェアの特性を把握しておくことが必要です。

ソースコード

繰り返しますが、「リトルエンディアンになってしまう」という意識でプログラムは組まないで下さい。「リトルエンディアンにする」、「ビッグエンディアンにする」という明確な意思と、妥協するのであれば考えた上で妥協する必要があります。

クラウドを使わずにバックアップが安心 ROBOCOPY と バックアップの習慣化

 皆さん、ファイルのバックアップは作成していますか? 私が聞いた限りでは「誰もやっていない」というのが正直なところです。ただ、そこまでパソコンというデバイスを信用しているのは怖いところです。 「良い道具は一生物」という言葉があります。実際、工具類は良いものを手に入れれば一生涯使え...