2012-06-04 23 views
7

私が使用する言語はCです。 xとnの型はintです。x = 0x80000000の場合、〜(x-1)と〜x + 1の差

それは、xの値を示し、nおよびXの補数のnビットをシフトさせる二つの方法

printf("x=%x,n=%d,first=%x,second=%x\n",x,n,((~(x+0xffffffff))>>n),((~x+1)>>n)); 

を次のように1行のコードを有しています。 x = 0x80000000、〜(x + 0xffffffff)= 0x8000000、〜x + 1 = 0x80000000の場合、これらの2つをnビットシフトすると結果は異なります。私は(〜1 + 1に0xFFFFFFFFを変更した場合

ところで、それは意味〜(X +(〜1 + 1))、その結果は〜X + 1

私はそれがなぜ起こったか疑問に思う。感謝と同じです。

+0

["(uint16_t)-1"ポータブルCコード?](http://embeddedgurus.com/barr-code/2011/06/is-uint16_t-1-portable-c-code/) – Lundin

+0

@ Lundinその記事は間違っています。 '(uint16_t)-1' **は実装が' stdint.h'でその型を提供するならば '0xFFFF'を生成する標準によって**保証されています。 (もちろん、それがあなた自身のtypedefなら何も保証されません)あいまいさはありません。固定幅型はパディングビットを必要としないので、値のビットにも制限されません(そうです。 'uintN_t'の値ビットだけです)。 –

答えて

4

intは普通の32ビットタイプと仮定して、Pavan Manjunathによって今削除された回答が1つのケースに対して正解でした。

0xffffffff 

定数整数値2^32 - 1を有し、それはintによって表現できないが、それはunsigned intとして表現可能です。そのタイプはunsigned int(6.4.4.1)です。したがってxを添加するためunsigned intに変換され、0 <= n < 32場合

((~(x+0xffffffff))>>n) 

は(nがこの範囲外である場合、それは未定義の動作です)値2^(31-n)

((~(0x80000000u + 0xffffffffu)) >> n) 
((~0x7fffffffu) >> n) 
(0x80000000u >> n) 

として評価されます。他の場合には

x = 0x80000000int~0x8000000 = 0x7fffffff = INT_MAXINT_MAX + 1符号付き整数オーバーフローとして未定義の動作である場合、ouahの答えは、正しいです。

しかし、一般的な動作はラップアラウンドであり、加算の結果は符号付き整数0x80000000であり、負の整数の右シフトは実装定義の動作(6.5.7)です。共通は符号拡張でシフトし、結果は-2^(31-n)となり、の値は2^32 - 2^(31-n)で、printfの変換指定子%xと解釈されます。

+0

は〜0符号付きまたは符号なし... – shirley

+0

'0'は' int'として表現できるので、 '〜0'の型も' int'です。 –

1

X = 0x80000000の、〜(X +は0xffffffff)= 0x8000000、〜X + 1 = 0x80000000から、32ビットintを有するシステムで

xを想定タイプintです) 2の補数符号付き表現であるこの式は、

~x+1 

は未定義の動作です。 x = 0x80000000~x == 0x7FFFFFFF == INT_MAXを意味し、INT_MAX + 1は未定義の動作です。したがって、~x + 10x80000000または他のものにすることができます。

次の式:

~(x+0xffffffff) 

一方は、定義された(0xffffffffがCでunsigned intある)と0x80000000に等しいです。 0xffffffffunsigned intであり、符号なし整数がC標準の意味で決してオーバーフローしないので、実際に定義されます。

これは、このステートメントことを意味します

printf("x=%x,n=%d,first=%x,second=%x\n",x,n,((~(x+0xffffffff))>>n),((~x+1)>>n)); 

は未定義の動作を呼び出し、それが両方の結果を比較しても意味がありません。

0

(sizeof(int)が4であると仮定すると、32ビットの符号付き値)。 0x80000000; //可能な最小負のint 0xFFFFFFFFを//で-2147483648は-1 2つ、0x7FFFFFFFでは、(int型の演算を使用)は、2つの和である 負から正への「ラップアラウンド」させる追加

ビット単位completent、または0x80000000の

あなたが任意の整数値から始めて、それから1を引く(またはそれに1を追加した場合は0x7FFFFFFFでの「〜」演算子を使用して2147483647

利回りである、それはしていませんあなたが十分な時間を過ごすと、あなたはそのサインを反転させます。これは、固定精度を使用した算術演算の基本的な問題です。

あなたの場合、この限定的な事例を気にすることなく、符号付き算術演算子とビット演算子を混在させることはできません。

2の補数演算を使用するときには非対称があります。正の数よりも負の数が1つ多いことに注意してください(ゼロを表す必要があるため残りの値に奇数のビット数が残ります)。

関連する問題