以前のマイコンで使っていたソースコードを移植して、
コンパイラのWarningを調べていたら符号なしの数値と負数の比較をしていると出てくる。
なんでそんなことになってるんだ? と調べて判明したのはchar型の取扱だった。
移植後のコンパイラでは char型を符号無しとして扱う設定がされていた。
そんな設定した覚えないのだが……と確認したら、標準設定がそれだった。
で、元々のマイコンのコンパイラはchar型は符号ありだったそうで、
ここが食い違いの原因だったらしい。
Cで単にintとかlongとか書けば符号ありなのだが、
charというのは符号の有無は環境依存だと定義されている。
このため符号ありと明示するには signed char、符号なしと明示するには unssigned char と書くべきとなっている。
それぞれ int8_t, uint8_t と書いた方が意図は明確かもしれない。
なぜこういうルールなのかというので調べるとこんなのが見つかった。
‘a’のような文字リテラルはchar型で負数ではないと規定されていて、
ASCIIコードの範囲であれば0~127なので符号付きの1byte型でも、符号無しの1byte型でも問題ない。
文字を表すという観点で言えば、0~255が表現できる符号無し型の方が有利である。
とはいえ、char型は文字の表現だけではなく1byteの数値表現にも使うことができる。
その観点では単にintと書けば符号ありになるのと同様、charも符号ありの方がよいという考えもある。
環境ごとにどちらが標準かというのはだいたい決まっているらしく、
確かに基本的にcharはunsignedと規定されていた。
旧来のマイコンは基本的にcharはsignedと規定されていたのだろう。
(少なくともコンパイラはそう解釈していたことは裏が取れている)
ゆえに流用コードをビルドするには signedと設定した方がよいようだ。
標準が符号なしというのは今まで気づいてなかったのだが、
char型が符号ありかなしか一意に決まらないということは知っていて、
Warningが出てる場所を少し調べたらすぐ見当は付きましたね。
くれぐれもご注意を。