1

unsignedcharが何であるかについて少し混乱しています。署名された文字は、ビット形式の文字の表現ですよね?サンプルの問題では、このソリューションでは符号なし文字のビットであるnビット位置だけ右に回転しています。

unsigned char rotate(unsigned char x, int n) {
    unsigned char temp = x << 8 - n;
    x = x >> n;
    return (x | temp);
}

誰かがcharの例とそれぞれのビットで説明できれば、それは大いにありがたいです。本当にありがとう。

4

3 に答える 3

3

signed charcharおよびunsigned charはすべて整数型です。簡単にするために、CHAR_BITは8であり、符号付き型は2の補数であると仮定します。それで:

  • signed char-128から+127までの数値です
  • unsigned char0から255までの数値です
  • charは、Cの実装に応じて、signed charと同じ範囲、またはと同じ範囲のいずれかです。unsigned char

Cに関する限り、文字はchar型の範囲内の単なる数値です(ただし、などのさまざまな文字関数tolowerでは、符号付きであっても、途中で値を符号なし型にキャストする必要がありますchar)。

したがって、signed charunsigned 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などのビット操作タスクでは、符号なしタイプを使用する必要があります。これにより、(型の幅以外の)実装依存性が排除され、負の値と非負の値を別々に推論する必要がなくなります。

于 2011-05-09T02:09:36.413 に答える
2

として変数を宣言するunsigned charと、基になるビットパターンを0(00000000)から255(11111111)までの数値として扱うようにコンパイラーに指示します。これを宣言するcharと、コンパイラは2の補数を基になるビットパターンに適用し、-128(10000000)から127(01111111)までの数値として扱うように指示されます。

3ビットの数値を考えてみましょう。署名されていない場合は、次のようになります。

000 = 0
001 = 1
010 = 2
011 = 3
100 = 4
101 = 5
110 = 6
111 = 7

署名されている場合は、次のようになります。

100 = -4
101 = -3
110 = -2
111 = -1
000 =  0
001 =  1
010 =  2
011 =  3

(リンクで言及されているように)算術に関して優れているのは、符号付き2進数を符号なし2進数とは異なる方法で処理する必要がないことです。符号付きまたは符号なしに関係なく、実際のバイナリ計算を実行するだけです。ただし、入力と出力に符号付き/符号なしの解釈を適用する必要があります。

署名されたレルムでは、次のようになります。

2 + (-3) = 010 + 101 = 111 = -1

しかし、符号なしの領域では、これは次のとおりです。

2 + 5 = 010 + 101 = 111 = 7

したがって、追加される実際のビットパターンと合計のビットパターンはどちらの場合も同じであるため、これはすべて解釈の問題です。

于 2011-05-09T01:27:54.127 に答える
1

unsigned charは、0〜255の値をとることができる8ビット整数型であり、signed charは-127〜128の値をとることができます。実際のマシンコードでは、1つを除いて実際の違いはありません。 >>(char、short、int)を使用した符号付き型の右シフトは、算術シフトとして実行されます。つまり、負の値(MSBとして1を持つ)の場合、0との代わりに1がシフトインされます。上記のコードは期待どおりに機能しません。

編集:符号付きおよび符号なしの符号なし文字を3ビットローテーションする上記のコード例:

00110101は符号なしでローテーションされ、符号付きは10100110です。

しかし、前に1が付いている数の場合、算術シフトが発生するため、

符号なしでローテーションされた11010001は00111010です。符号付きでローテーションされ
た11010001は11111010です。

于 2011-05-09T01:31:27.820 に答える