[迷信] char 型は符号付き

short, int, long と同じく、signed も unsigned も付けなければ、デフォルトで符号付きという類推が働くからか、あるいは普段使っている処理系がたまたまそうだったからか、char 型の表現範囲は -128〜+127 であると堅く信じているプログラマは少なくありません。

[迷信] 1 バイトは 8 ビットでも指摘したように、char 型は 8 ビットとは限りません。それだけでなく、char 型は符号付きか符号無しかも処理系定義です。ですので、char 型が -128〜+127 であるという決めつけは、これら二つの意味で間違っています。

6.2.5 型 (中略)
 三つの型char, signed char及びunsigned charを総称して文字型(character type)と呼ぶ。処理系は,charを,signed char又はunsigned charのいずれかと同じ値の範囲,同じ表現形式,そして同じ動作をするものとして定義しなければならない。

JIS X3010:2003より引用

3.9.1 基本型 文字(char)として宣言されたオブジェクトの大きさは,処理系定義である基本文字集合のすべての要素を格納するのに十分なだけ大きくなければならない。(中略)charオブジェクトが負の値をもてるか否かは,処理系定義とする。

JIS X3014:2003より引用

二つの規格から引用しました。上段は標準 C、下段は標準 C++ の規定です。いずれも、char 型が符号付きか符号無しかは処理系定義であることが明記されています。

ところで、処理系定義というと、コンパイラが決まれば char 型が符号付きか符号無しかが決まるように考えてしまいがちです。しかし、現実はそれほど単純ではありません。例えば、GCC の場合には、ターゲットによって char 型が符号付きか符号無しかが変わります。

また、コンパイルオプションによっても変わります。例えば、GCC の場合、-funsigned-char または -fsigned-char オプションを指定することで、char 型が符号無しなのか符号付きなのかを設定できます。Visual C++ では、デフォルトでは符号付きですが、/J オプションを指定すれば符号無しになります。

日本語のように、多バイト文字を多用する言語環境の場合、char 型は符号無しの方が何かと便利です。では、unsigned char を使えばよいかというと、C の場合はそれでもかまいませんが、C++ ではそうはいきません。単なる char、signed char、および unsigned char はそれぞれ別の型だからです。型が異なるということは、多重定義やテンプレートの解決に影響しますので、unsigned char を使うというわけにはいかないのです。

参考

この記事のトラックバックURL:

http://www.kijineko.co.jp/trackback/543