私はかなり探し回ったが、この一見単純な質問に対する答えを見つけることができないようだ: C (ビット) の「+」または「-」とは正確には何ですか?
例えば、11111111 11111111 11111111 11111111 に 1 を足したときの表現は?
私はいくつかのコードを読んでいて、何がわからないので、これを尋ねます
~0 + 1
やっています。つまり、4294967295 に 1 を足すことはできませんよね?
ありがとう!
答えは、コンピューターが署名付きの数値に使用する表現によって異なります。
「2 の補数」形式では、~0 == -1
、そう~0 + 1 == 0
.
「一の補数」形式では、~0 == -0
、そう~0 + 1 == 1
.
「サインマグニチュード」形式では、~0 == INT_MIN
、そう~0 + 1 == INT_MIN + 1
.
結果は、すべてのシステムで定義されることが保証されています。
一方、符号なしの数値を使用すると、常に同じ結果が得られます。
~n
はn
の型の最大値マイナスと定義されていますn
。そう~0u
ですUINT_MAX
。
x + y
ラップアラウンドが保証されているため、標準でUINT_MAX + 1 == 0
はすべてのシステムでラップアラウンドが保証されています。
したがって、~0u + 1 == 0u
すべてのシステムで保証されます。
ご覧のとおり、これは 2 の補数と同じ動作であり、これが 2 の補数の人気を説明しています。2 の補数を使用しないシステムは、bigint ライブラリを除いて、最近ではまれです。
もちろん、我々はできます。リテラルの型を指定しなかったため、「int」が想定されます。~0
は-1
、あなたが示したように、-1 + 1
ゼロです。
一方、これらが符号なしの数値である場合は、整数オーバーフローが発生しています。PC の奥深くにある実際の add 命令は、まだゼロを返します。何か奇妙なことが起こったことを C に知らせるために、'carry' フラグを設定するだけです。C 仕様では、整数オーバーフローの結果は定義されていないため、/おそらく/ゼロになりますが、それに頼ることはできません。
何が起こっているのかを簡単に確認できるように、小さい数値に固執しましょう。
4 ビットの数値は0000
. 1111
今から始めて、それに1つ追加してください。値は現在1 0000
、 として表示され0000
ます。
通常の10進足しと同じです。9
次に0
、1 の位と10 の位があり1
ます。数がビット数よりも大きい場合、カウンターは 0 にロールオーバーして最初からやり直します。
さて、これは正の数について話すために単純化されています。int が符号付きの場合、最大の正から最大の負に移動し、最大の正にループバックして、最終的に負の数と正の数をバイナリに格納する方法を実行します。
2^32=4294967296
したがって、2^32-1
は 32 ビットの符号なし整数 (2 進数で 32 桁) の最大値です。2^32 は可能な値の数です。
4294967295 は、整数が 0 から始まるためですが、カウントは 1 から始まります。
これは整数の範囲です。この数値に 1 を追加すると、整数の範囲外になります。そのため、4294967295 に 1 を追加することはできません。
+
は加算算術演算子です &-
は減算算術演算子です
技術的には、C は追加も抽出もしません。コンパイラはそれをアセンブリ コードに変換し、アセンブリ コードはマシン コードに変換されます。アーキテクチャにはADD
命令が必要です。
基本的な論理ゲートを使用して、いくつかの方法で操作を実行できると思います。
とにかく、この本にはいくつかの情報があります。
また、負の数が 2 進数でどのように表されるか、およびこれが算術演算にどのように適合するかについても興味があるかもしれません。
使用される一般的な形式は、 2 の補数と呼ばれます。これがどのように機能するかについて詳しくは、こちらをご覧ください。