符号なし変数に負の値を割り当てるとどうなるか知りたいと思いました。
コードは次のようになります。
unsigned int nVal = 0;
nVal = -5;
コンパイラエラーは発生しませんでした。私がプログラムを実行したときnVal
、奇妙な値が割り当てられました!2の補数の値が割り当てられる可能性がありnVal
ますか?
符号なし変数に負の値を割り当てるとどうなるか知りたいと思いました。
コードは次のようになります。
unsigned int nVal = 0;
nVal = -5;
コンパイラエラーは発生しませんでした。私がプログラムを実行したときnVal
、奇妙な値が割り当てられました!2の補数の値が割り当てられる可能性がありnVal
ますか?
nVal = (unsigned int) -5;
。と同等です。-5
toのキャストは6.3.1.3unsigned int
で定義されています。2の補数での表現は標準では義務付けられていませんが、符号なしに変換するアルゴリズムは次のとおりです。「値が範囲内になるまで、newtypeで表現できる最大値より1つ多い値を繰り返し加算または減算することにより、値が変換されます。ニュータイプの」
回答:
公式の回答について-セクション4.7conv.integral
「宛先タイプが符号なしの場合、結果の値はソース整数と一致する最小の符号なし整数です(モジュロ2 n、ここ
n
で、は符号なしタイプを表すために使用されるビット数です)。[注:2の補数表現では、この変換は概念的であり、ビットパターンに変更はありません(切り捨てがない場合)。— end note]
これは基本的に、基礎となるアーキテクチャが2の補数ではないメソッド(符号付きの大きさや1の補数など)に格納されている場合、符号なしへの変換は2の補数であるかのように動作する必要があることを意味します。
-5(2の補数)を表すビットパターンをunsignedintに割り当てます。これは大きな符号なしの値になります。32ビットintの場合、これは2 ^ 32-5または4294967291になります。
ceil(log_2(x))
。)
これは、最大符号なし整数-4の値の正の整数として表示されます(値はコンピューターアーキテクチャーとコンパイラーによって異なります)。
ところで
、これは単純なC ++の「helloworld」タイプのプログラムを作成して確認し、自分の目で確かめることができます。
そうです、符号付き整数は2の補数形式で格納され、符号なし整数は符号なしバイナリ表現で格納されます。C(およびC ++)は2つを区別しないため、最終的に得られる値は、2の補数のバイナリ表現の符号なしバイナリ値にすぎません。
はい、その通りです。割り当てられる実際の値は、3番目を除くすべてのビットセットのようなものです。-1はすべてのビットが設定され(16進数:0xFFFFFFFF)、-2は最初のビットを除くすべてのビットです。表示されるのは、おそらく16進値0xFFFFFFFBで、10進数で4294967291に対応します。
符号なし変数に負の値を割り当てると、2の補数法を使用して処理します。この方法では、すべての0を1に、すべての1を0に反転してから、1を加算します。あなたの場合、4バイト(32ビット)のintを扱っているので、32ビット数で2の補数法を使用しようとします。これにより、上位ビットが反転します。例えば:
┌─[student@pc]─[~]
└──╼ $pcalc 0y00000000000000000000000000000101 # 5 in binary
5 0x5 0y101
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010 # flip all bits
4294967290 0xfffffffa 0y11111111111111111111111111111010
┌─[student@pc]─[~]
└──╼ $pcalc 0y11111111111111111111111111111010 + 1 # add 1 to that flipped binarry
4294967291 0xfffffffb 0y11111111111111111111111111111011