char型を文字列以外の用途で用いちゃいけない訳

 急に思い出したけど僕は開発者なので、たまには開発者っぽいことも書いていこうと思う。C言語の話。先日char型の変数のせいでえらい目にあった。
 簡単なコーディングなので見てみてほしい。例えば下記のようなコード。


char flag = -1;
if (flag == -1) {
hoge();
}

 このコード、char型のflagが-1になっていたら、hoge()関数が実行されるんですが、先日僕がこのようなプログラムを動かしたところ、どうもhoge関数が実行されない。だってif文の前で-1ってやってんだよ!? 意味分からないじゃない?
 したらお前、ここがC言語というかコンパイラの罠ですよ。

if(flag == -1)

の判定文。なんとflagが4バイトのintにキャストされてたわけです。しかもえらく変な感じでキャストされてた。charは1バイトの整数値なので、それがintにキャストされるとどうなるかと言うと、

符号付きcharの-1の16進数表記 : FF → -1
↑を4バイトintにキャストしたときの16進数表記:00 00 00 FF → 255

つまり僕が直前で-1と定義した値がすばらしきコンパイラさんのおかげで255になっていたわけです。そら駄目だ。
 もちろん頭のいいコンパイラによっては、intにキャストしたとしても-1として扱ってくれる事もあります。が、僕のプロジェクトで使ってる妙な野良コンパイラはアホなのでこういうことになったわけ。
 でもでも。コンパイラがアホだからーで済ませる問題ではない。このコード、頭いいコンパイラでコンパイルされるとは限らないからだ。通常、書いたコードが他に流用されないなんてことはあり得ない。色んなプロジェクトで流用されると考えたほうがよい。流用されるプロジェクトによってはアホコンパイラもあるだろうし、賢いコンパイラもいるわけで。そういった事を考えるとコンパイラ依存の上記コードは絶対書いちゃいけない。
 だから、こう直しましょうね。っていう話。

int flag = -1; ★
if (flag == -1) {
hoge();
}

 バカみたいな話だけど、misra-cのコーディング規約にも明記されている話だったりする。

http://www.openrtp.jp/wiki/_hara/ja/RtORB/MISRA-C-RULE.html

6.1 R 単なるchar型は、文字データの格納及び使用に限って用いなければならない。
6.2 R signed char型及びunsigned char型は、通知データの格納及び使用に限って用いなければならない。

この1文だけ見ると、なんで? って思いますがこういう事例があるとよく分かりますね。
 そもそも僕がこんなflagをchar型で定義してしまったのは、なぜかAndroidで書いたコードをC言語に流用してよ? 流用だから簡単でしょ? 3キロLineを1ヶ月で。とかキチガイみたいなことを言われ、時間もねーしjavaのbyte型をそのままcharに置換してたからで、最初からC言語で書いてたらこういうことはしなかったっつーかぶつぶつ……
【ニコ動でゲーム実況してました。】
ニコニコ動画ゲーム実況一覧

【twitter】気軽にフォローしてください→@yhei_hei