ファイルデータ読み込み時のEOF判定(型に注意)

C言語でバイナリファイのダンププログラムを書いていた際に、
EOFの判定部分でハマったのでメモ。


バイナリファイルを最後まで読み込むときにはEOF(-1)を
読み込みの終了条件にすることが多い。

ファイルから1byteずつ読み込んでダンプしたい場合に
読み込みデータをsigned char型 or unsigned char型変数に格納すると、
ファイルの途中で0xff(-1)があった場合に
そこでファイルの読み込みが終了してしまう。
(0xffとEOFが区別できない)

なので、読み込みデータはint型変数に読み込む必要がある。
そうするとEOFの際は0xffffffff、ファイル内の0xffは0x000000ffが
変数に格納されるので、両者を区別できる。

以下がサンプルプログラム。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE *fp = NULL;

    // while文の比較でEOF(-1)とファイル内の0xffとを区別するため、charでなくintで宣言
    // これにより、ファイル内の0xffは0x000000ff, EOFは0xffffffffとなるので比較段階で区別できる
    int mask = 0;
    int c    = 0;

    mask = (unsigned char)strtol(argv[2], NULL, 16);

    if ( ( fp = fopen(argv[1], "r") ) == NULL )
    {
        printf("file open error!\n");
	return 1;
    }

  // cに格納される値を上記コメントの要領で判定
    while( ( c = fgetc(fp) ) != EOF )
    {
        c ^= (unsigned char)mask;
        printf("%x", (unsigned char)c);
    }
	printf("\n");

	fclose(fp);
	return 0;
}

参考サイト:
C言語でEOFをchar型で比較してまずいのはなぜ? | 株式会社シンメトリック公式ブログ |