signed char と unsigned charの違い

[戻る]
yoss- 2002/05/21(火) 23:11:48
signed int と unsigned intの違いは表せる数字の範囲が違うのは分かるのですが、
signed char と unsigned charの違いが分かりません。

charは基本的に文字として取り扱う為、第一ビットが+-の符号であろうが
関係ないと思うので、signed charだけあれば十分な気がするのですが。
signed charだけでは何か不都合があるのでしょうか?

Win98 + Win2000
VC++6.0
MFC

YuO [E-Mail] 2002/05/21(火) 23:24:45
charはC/C++の文法的には,
「最低8bitのサイズがあり,1byteの大きさである特殊な整数型」
になります。
#符号の有無は実装定義。

というわけで,shortより小さい整数型が欲しいときに,
unsigned charやsigned charを使います。
バイナリを扱う気には,明示的にunsigned charとすることも多いです。

ちなみに,charの符号の有無に関わらず,charとsigned charとunsigned charは別の型です。

yoss- 2002/05/22(水) 00:21:24
YuOさん素早いレスありがとうござます。

>というわけで,shortより小さい整数型が欲しいときに,
>unsigned charやsigned charを使います。
>バイナリを扱う気には,明示的にunsigned charとすることも多いです。
バイナリを扱うときにunsigned charにする事が多いと言う事はsigned charでも特に問題ない
のでしょうか?
例えば0xFFのバイナリデータがあった場合
unsigned char → 255
  signed char  → -1
ですが、結局はどちらも0xFFなので数字を足したり引いたりしない限り問題ないという認識で
宜しいでしょうか?

>ちなみに,charの符号の有無に関わらず,charとsigned charとunsigned charは別の型で
す。
私の認識ではsigned char と unsigned charの違いは符号の有無だけの違いで
charは処理系によってsigned charにであったり、unsigned charであると思っているのです
が、この考え方自体違うのでしょうか?

YuO [E-Mail] 2002/05/22(水) 01:19:49
> バイナリを扱うときにunsigned charにする事が多いと言う事はsigned charでも特に問
題ない
> のでしょうか?

扱い方を間違えなければsigned charでも問題ないです。
ただ,思わぬバグの原因になる可能性は十分にあります。


> ですが、結局はどちらも0xFFなので数字を足したり引いたりしない限り問題ないという
認識で

単純にstorageの型として使う分には問題ないです。
ただ,演算を行うときは,unsignedの方がバグが少ないです。


> 私の認識ではsigned char と unsigned charの違いは符号の有無だけの違いで
> charは処理系によってsigned charにであったり、unsigned charであると思っているのです
> が、この考え方自体違うのでしょうか?

間違っています。
ISO/IEC 14882:1998 3.9.1 Fundamental typesには,
> Plain char, signed char, and unsigned char are three distinct types.
とありますし,同じくISO/IEC 9899:1999 6.2.5 Typesの脚注35には,
> Irrespective of the choice made, char is separate type from the other two and
is not compatible with each other.
とあります。
#脚注35のother twoはsigned charとunsigned charのこと。

つまり,C++では
char func (char);
signed char func (signed char);
unsigned char func (unsigned char);
という関数のオーバーロードが可能ですし,
char *char_ptr;
signed char * signed_char_ptr;
signed_char_ptr = char_ptr;
unsigned char * unsigned_char_ptr;
unsigned_char_ptr = char_ptr;
というコードは,C++ではエラーを2つ生成し,
Cではコンパイラによってはwarningが生成されると思います。

駄犬 [E-Mail] 2002/05/22(水) 12:15:33
>バイナリを扱うときにunsigned charにする事が多いと言う事はsigned charでも特に問題な>のでしょうか?
(snip)
>ですが、結局はどちらも0xFFなので数字を足したり引いたりしない限り問題ないという認識で
>宜しいでしょうか?

1バイト同士の加算、減算では問題になることはないでしょう。
問題になる可能性があるのは大小比較やシフト演算。(他にもあるかな?)
値によっては符号付と符号無しで結果が異なることがあるのはお分かりかと思います。
この違いを意識しなければ思わぬバグを生むことになります。
(いや、バグというのは常に思わぬものなのですけどね。:-))

yoss- 2002/05/22(水) 22:46:37
YuOさん,駄犬さんレス有り難うございます。

何度も読み返して今私が理解した部分は、
signed char / unsigned charは文字を扱う場合大差はなく
数字として扱う場合は符号による区別がある、
また、バイナリデータを扱う場合は0xFFというデータがありうる為
基本的にはunsigned charで扱う方がbestである、しかしsigned charでも特に問題ないという
ことです。

char / signed char / unsigned char の三種類のcharに付いては、
コンパイラでは違う型として認識するが、実際のデータの扱い方は処理系によってsigned char
にであったり、unsigned charであるという事ででしょうか?

>扱い方を間違えなければsigned charでも問題ないです。
>ただ,思わぬバグの原因になる可能性は十分にあります。
これは、四則演算をした場合に思わぬバグが発生すると言う事で宜しいのでしょうか?

yoss- 2002/05/22(水) 22:49:54
すみません以下の文を訂正します

>また、バイナリデータを扱う場合は0xFFというデータがありうる為
>基本的にはunsigned charで扱う方がbestである、
>しかしsigned charでも特に問題ないということです。
また、バイナリデータはマイナスがありえない為
基本的にはunsigned charで扱う方がbestである、
しかしsigned charでも特に問題ないということです。

YuO [E-Mail] 2002/05/23(木) 02:49:14
> signed char / unsigned charは文字を扱う場合大差はなく

signed char *やunsigned char *では,std::strlenなどの標準関数が使えなくなります。
#operator<<(std::basic_ostream, const signed char *);などはありますが。
また,std::basic_string<signed char>や<unsigned char>も,
std::char_traits<signed char>などの特殊化がなされていないため,
扱いにくいと思います。

もちろん,ハナからC/C++の標準ライブラリを無視すれば,
char/signed char/unsigned charに違いはあまりないです。
#テンプレートは使いにくいですが。


> また、バイナリデータはマイナスがありえない為
> 基本的にはunsigned charで扱う方がbestである、
> しかしsigned charでも特に問題ないということです。

わざわざsignedを付けることは普通ないです。
扱いにくくするだけですから。

ちなみに,unsigned charの最大値は0xFFとは限りませんよ。
#今時1byteが8bit以外のコンピュータも珍しいとは思いますが。

> char / signed char / unsigned char の三種類のcharに付いては、
> コンパイラでは違う型として認識するが、実際のデータの扱い方は処理系によって
signed char
> にであったり、unsigned charであるという事ででしょうか?

そうです。
ただ,文字以外を扱う場合にcharは使わない方がよいです。
#処理系定義の動作が絡んでくるため。


>>扱い方を間違えなければsigned charでも問題ないです。
>>ただ,思わぬバグの原因になる可能性は十分にあります。
> これは、四則演算をした場合に思わぬバグが発生すると言う事で宜しいのでしょうか?

四則演算だけでなく,例えば,ダンプを出力しようとして,
signed char buffer[256];
int i;

for (i = 0; i < 256; ++i) {
    printf("%02X ", buffer[i]);
    if (i % 8 == 7) puts("");
}
なんてことをやると,思わぬ値が表示されてデバッグに手間取るかもしれません。

signed charを使うと,上のような簡単なプログラムでバグを混入させてしまいます。
unsigned charを使っていれば,上記のプログラムにバグは無いのです。
気を付ければ,と思うかもしれませんが,
>(いや、バグというのは常に思わぬものなのですけどね。:-))
なのです。
バグを作らないためには,バグが混入しないようなプログラムを作らないといけません。

yoss- 2002/05/23(木) 21:29:40
[[解決]]
本を見ても解答が得られず困っていたので大変助かりました。
これからプログラムを組む時には教えて頂いた事に注意しながら組もうと思います。
親切に教えて頂きありがとうございました。

古いスレッドには追加発言できません。