6

K&R ANSI C ブックのセクション A.7.4.5 (単項マイナス演算子) には、次のように記載されています。

... 符号なし数量の負数は、昇格された型の最大値から昇格された値を減算し、1 を加算することによって計算されます。...

これはどのように正確に計算されますか?簡単な C の例を教えてください。

これが、たとえば 200u の負の値を生成する方法がわかりません。任意の整数型 (符号付きまたは符号なし) の最大値から 200 を減算し、1 を加算しても -200 にはなりません。

単項マイナスが何をするかは知っています。問題は、説明に従って結果がどのように計算されるかがわからないことです。

4

6 に答える 6

9

符号なしの値を負にすることはできないため、-200 は可能な結果ではありません。

それが言っているのはUINT_MAX、あなたのシステムで が 65535 の場合、次の結果になるということです:

unsigned a = 200;
unsigned b = -a;
long c = -a;

bと の両方に65336 が残りcます。

システムにある場合UINT_MAX > LONG_MAX(通常はintとが同じサイズであるため)、 forlongを使用する必要があります(ただし、十分な長さであるという保証さえないことに注意してください)。long longc

この詳細 (符号なしの数値を否定した結果は別の、必然的に正の符号なしの数値になるということ) を理解していないと、予期しない結果が生じる可能性があります。たとえば、次のコードでは、最初の例では出力されます"true"が、2 番目の例では次のように出力され"false"ます。

int a = 200;
unsigned b = 200;
if (-a < 100) printf("true\n"); else printf("false\n");
if (-b < 100) printf("true\n"); else printf("false\n");

(否定演算子の結果をどこにも保存していないことに注意してください - それは問題ではありません)。

于 2009-11-09T12:36:22.270 に答える
8

どうやら、引用した説明でunsignedという単語を見逃していたようです。これがこの場合のキーワードです。C 言語では、符号なし数量の「負」は符号なしのままであり、実際には負ではないことを意味します。定義により、符号なしの値が負になることはありません。それらは常に正または 0 です。C における符号なしの値の算術演算はモジュロ算術です。つまり、単純に言えば、算術演算を実行すると、符号なしの量が「ラップ アラウンド」します。単項否定も例外ではありません。が unsigned である-nときの計算は、 の計算と同じです。が であり、その値が である場合、期待される結果はではなくであり、これはまさに引用が伝えていることです。n0 - nnunsigned int200-200UINT_MAX - 200 + 1

于 2009-11-09T17:05:27.837 に答える
6

モジュラ算術を実装するための操作について説明します。つまり、次のような値を計算します。

a + (-a) == 0

これにより、否定された符号なし数値は、否定された符号付き数値と同様に動作します。

数値表現が2 の補数であるマシン(x86 など) では、これは、符号なし数値のビット パターンを通常の符号付き数値として扱い、マシンの標準の「否定」命令を使用することによって行われます。

于 2009-11-09T12:36:24.900 に答える
4

符号なし整数型の操作では、剰余算術が使用されます。m を法とする算術演算は、通常の算術演算とほとんど同じですが、学校で遭遇したことがなければ、m で割ったときに結果が正の剰余になる点が異なります (詳細については、ウィキペディアの記事を参照してください。たとえば、7 - 3モジュロ 10 は 4 ですが、3 - 7 モジュロ 10 は 6 です。これは、3 - 7 が -4 であるためです。これを 10 で割ると、商が -1 になり、剰余が 6 になります (商が 0 で表され、 -4 の剰余, しかしモジュラ算術ではそうはいきません). m を法とする可能な整数値は 0 から m-1 までの整数です. 負の値はあり得ず, -200 は有効な unsigned ではありません.どんな状況でも価値があります。

現在、単項マイナスは負の数を意味し、m を法とする有効な値ではありません。この場合、符号なし整数から始めているため、0 から m-1 の間であることがわかります。したがって、-k を m で割ることを検討しています。1 つの可能な値は商 0 と -k の剰余であるため、別の可能な値は商 -1 と mk の剰余であるため、正解は mk です。

C の符号なし整数は通常、モジュラスではなく最大値で記述されます。つまり、符号なし 16 ビット数は、通常、0 ~ 65535、または最大値 65535 として記述されます。 m ではなく m-1 です。

あなたが持っている引用は、負の値は m-1 からそれを引いてから 1 を加えることによって得られると言っているので、-k は m - 1 - k + 1、つまり m - k です。説明は少し遠回りですが、既存の定義に関して正しい結果を指定しています。

于 2009-11-09T18:13:21.070 に答える
4

別の質問がすでにこのトピックに触れています

unsigned char i = -10;
printf("%u\n",i);

結果

246
于 2009-11-09T12:44:08.197 に答える