読者です 読者をやめる 読者になる 読者になる

gggggraziegrazie

graizegrazieさんのやったこと、学んだことを記録する雑記帳です

C/C++で配列の初期化に#includeを使う

 データファイルを取り扱う時、そのデータを読んで配列に格納していくのは面倒ですよね。実は、配列の初期化には#includeプリプロセッサが使えます。今回は#includeを使って配列を初期化した時の挙動について書きます。

 なお今回のテスト環境は、

で、includeするファイルはソリューションファイルと同じディレクトリに存在するものとします。

使用コード・ファイル

 今回の実験には、#includeで初期化した配列をprintfで各要素を表示するソースコードと、4つの数字","で区切られたデータファイルを使いました。それぞれの内容は下記の通りです。

ソースコード

#include "stdio.h"

int sample[] = 
{
#include "sample.txt"
};

int main(void)
{
 unsigned int i;
 unsigned int buf_size;

 buf_size = sizeof(sample) / sizeof(int);
 printf("Size of buffer(sample) is %d\n", buf_size);

 for (i = 0; i < buf_size; i++)
 {
   printf("element%2d: %d\n", i, sample[i]);
 }

 return 0;
}

sample.txtの中身

1,2,3,4

実験1(上記ソースコードをただ実行する)

 上記のソースコードを実行すると、#includeプリプロセッサがsample.txtの中身を読んで、配列を初期化してくれることが期待されます。実行してみた結果、実際にそうなりました。この時のコマンドプロンプトの表示を、Fig.1に示します。ファイルポインタを使わなくてよいことから、ファイルポインタ操作(fcloseとか)が不要になるのが便利ですね。

f:id:graziegrazie:20150721100927p:plain
Fig.1 サンプルコード実行時のコマンドプロンプト表示結果

実験2(配列のサイズをsample.txtの要素より少なくしてみる)

 #includeがsample.txtの中身を読んでいることから、例えばsample[3]とすると、コンパイルエラーが発生することが予想されます。実際に試してみた結果、Fig.2のようになりました。ファイルの中身を読んでいることがここから分かります。

f:id:graziegrazie:20150721102341p:plain
Fig.2 サンプルコード中の配列サイズをsample.txtの中身より小さくした時のコンパイル結果

まとめ

 C/C++では、配列の初期化に#includeプリプロセッサを使い、初期化時にファイルの中身を直接配列に保存することができます。これにより、ファイルポインタの解放忘れがなくなり、メモリ関係のトラブル要因を1つ消すことができます。また、実行環境でファイルを読まなくてよいので、秘密なデータを配列に保存したい時、セキュリティの面から有用だと思います。
 また、配列サイズを指定する・しないをうまく使い分けることで、様々なメリットがあると考えます。自分の考えとしては、
 -サイズを指定する →読み込むファイルの中身のサイズが固定
           →読み込むファイルが想定したファイルか、フォーマットになっているかが確認できる

 -サイズを指定しない→読み込むファイルのフォーマットが変わっても、柔軟に対応することができる
というメリットがあると思います。
 ただし、#includeを使って配列を初期化すると、コンパイル時に配列サイズが決まってしまいます。つまり、ファイルの中身を変更しそれを配列に反映したい時、再コンパイルが必要になります。この点には注意が必要になります。