signed char
、char
およびunsigned char
はすべて整数型です。簡単にするために、CHAR_BITは8であり、符号付き型は2の補数であると仮定します。それで:
signed char
-128から+127までの数値です
unsigned char
0から255までの数値です
char
は、Cの実装に応じて、signed char
と同じ範囲、またはと同じ範囲のいずれかです。unsigned char
Cに関する限り、文字はchar
型の範囲内の単なる数値です(ただし、などのさまざまな文字関数tolower
では、符号付きであっても、途中で値を符号なし型にキャストする必要がありますchar
)。
したがって、signed char
とunsigned char
は両方ともビット形式の文字の表現です。0から+127の範囲の数値の場合、どちらも同じ表現を使用します(正の数値を2進数で表す方法は1つしかありません)。その範囲外の数値の場合、負の数の符号付き表現は、 (2の補数の定義)n
の符号なし表現と同じビットです。n + 256
このコードが使用する理由unsigned char
は、負の符号付きの値を使用した右シフトが実装定義の結果をもたらすためです。負の符号付きの値を使用した左シフトの動作は未定義です。通常、左シフトは符号なしの値の場合と同じように動作しますが、右シフトは値1のビットを左側に挿入します。これは、いわゆる「算術シフト」であり、ここでは必要ありません。符号なしの値は常にゼロにシフトインします。このコードがローテーションされた結果の2つの部分を構築したり、それらを一緒に構築したりできるのはゼロのシフトインです。
したがって、入力値をx = 254(11111110
)、n = 1とすると、次のようになります。
x << 7 is 0111111100000000
x >> 1 is 01111111
| is 0111111101111111
convert to unsigned char to return is 01111111
の代わりに符号付きタイプを使用した場合、次のunsigned char
ようになる可能性があります。
x is -2 11111110
x << 7 is 11111111111111111111111100000000 (assuming 32-bit int, since
smaller types are always promoted to int for arithmetic ops)
x >> 1 is implementation-defined, possibly
11111111111111111111111111111111
| is 11111111111111111111111111111111
convert to signed char to return is -1
したがって、unsigned charを使用したビット操作では、正解が得られ、1ビット回転して0を最後から最初に移動します。符号付き文字を使用したビット操作は、おそらく間違った結果をもたらし、負の符号付き値が論理的な右シフトを行う場合は正しい結果をもたらす可能性がありますが、実際には珍しい実装では何でもできます。
ほとんどの場合、rotateなどのビット操作タスクでは、符号なしタイプを使用する必要があります。これにより、(型の幅以外の)実装依存性が排除され、負の値と非負の値を別々に推論する必要がなくなります。