web-dev-qa-db-ja.com

C:符号なしオペランドを使用した単項マイナス演算子の動作

符号なしオペランドを使用した単項マイナス演算子の動作を完全に定義しているC標準の関連部分を見つけることができないようです。

2003年のC++標準(はい、C++、数行は私に耐えます)は5.3.1c7で次のように述べています:_The negative of an unsigned quantity is computed by subtracting its value from 2^n, where n is the number of bits in the promoted operand._

ただし、1999 C標準には、そのような明示的なステートメントが含まれておらず、単項演算を明確に定義していません。6.5.3.3c1,3でも6.5c4でも動作しません。後者では、Some operators (the unary operator ~, and the binary operators <<, >>, &, ^, and |, ...) ... return values that depend on the internal representations of integers, and have implementation-defined and undefined aspects for signed types.)と書かれていますが、これは単項マイナスを除外しており、物事はあいまいなままのようです。

この以前の質問 は、K&R ANSI Cの本、セクションA.7.4.5に_The negative of an unsigned quantity is computed by subtracting the promoted value from the largest value of the promoted type and adding one_と記載されています。

本からの上記の引用に相当する1999C標準は何でしょうか?

6.2.5c9によると:_A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type._

それですか?それとも私が欠けているものは他にありますか?

33
Alexey Frunze

はい、6.2.5c9はまさにあなたが探していた段落です。

16
Roland Illig

符号なしオペランドでの単項マイナス演算子の動作は、マシンが符号付き数値で2の補数演算を使用するかどうかとは関係ありません。代わりに、_unsigned int x,y;_が与えられると、ステートメント_y=-x;_により、yは、_x+y_をゼロに等しくするために保持する必要のある値を受け取ります。 xがゼロの場合、yも同様にゼロになります。 xの他の値の場合、それは_UINT_MAX-x+1_になります。この場合、_x+y_の算術値はUINT_MAX+1+(y-y)になり、_unsigned integer_は、_UINT_MAX+1_が減算され、ゼロになります。

8
supercat

私が知っているすべての実装では、負の数は 2の補数 ..として計算されます。

int a = 12;
int b = -a;
int c = ~a + 1;
assert(b == c);

...したがって、負の符号付き整数と「負の」符号なし整数の間に実際には物理的な違いはありません。唯一の違いは、それらが解釈される方法にあります。

したがって、この例では...

unsigned a = 12;
unsigned b = -a;
int c = -a;

... bcにはまったく同じビットが含まれます。唯一の違いは、bが2 ^ 32-12(または2 ^ 64-12)として解釈されるのに対し、cは「通常」-12として解釈されることです。

したがって、負の値は「符号」に関係なくまったく同じ方法で計算され、符号なしと符号付きの間のキャストは実際にはノーオペレーションです(一部のビットを「カットする必要がある」という意味でオーバーフローを引き起こすことはありません。 -オフ")。

3