私は自分のプログラムがなぜ
#include<stdio.h>
void main()
{
printf("%x",-1<<4);
}
印刷しfffffff0
ます。
このプログラムは何をしていて、<<
オペレーターは何をしていますか?
私は自分のプログラムがなぜ
#include<stdio.h>
void main()
{
printf("%x",-1<<4);
}
印刷しfffffff0
ます。
このプログラムは何をしていて、<<
オペレーターは何をしていますか?
<<
演算子は左シフト演算子です。の結果はa<<b
ビットのa
左側にシフトされます。b
コードの問題は、負の整数を左シフトしていることです。これにより、未定義の動作が発生します(ただし、コンパイラーはこの操作にいくつかの保証を設定する場合があります)。また、%x
符号なし整数を16進数で出力するために使用され、符号付き整数をフィードします。これも未定義の動作です。
表示されているものが表示されている理由については、2の補数アーキテクチャ-1
は「すべてのもの」として表されます。したがって、32ビットのコンピューターでは次のようになりint
ます。
11111111111111111111111111111111 = -1 (if interpreted as a signed integer)
これを4つの位置の左側にシフトすると、次のようになります。
11111111111111111111111111110000
%x
指定子makeはprintf
、これを符号なし整数として解釈します。これは、16進表記では。です0xfffffff0
。これは、4つの2進数が1つの16進数に等しいため、理解しやすいです。バイナリの1111
グループはf
16進数になり、0000
バイナリの最後0
は16進数の最後になります。
繰り返しになりますが、ここで説明するこの動作はすべて、特定のコンパイラが機能する方法です。C標準に関する限り、これはすべてUBです。これは非常に意図的なものです。歴史的に異なるプラットフォームでは負の数を表す方法が異なり、さまざまなプロセッサのシフト命令には微妙な違いがあるため、シフト演算子で得られる「定義された動作」は、多かれ少なかれほとんどの人に共通の「安全なサブセット」です。 「通常の」アーキテクチャ。
これは、-1のビット表現を取り、それを左に4回シフトすることを意味します
これは取る
11111111 11111111 11111111 11111111 = ffffffff
そしてシフト:
11111111 11111111 11111111 11110000 = fffffff0
"%x"
フォーマット指定子とは、16進表記で出力することを意味します。
これは左シフト二項演算子です。-1x4ビットシフトしたままです。
-1 == 1111 1111 1111 1111 1111 1111 1111 1111(2) == FFFFFFFF
-1 << 4 == 1111 1111 1111 1111 1111 1111 1111 0000(2) == FFFFFFF0
「%x」は、整数が16進値で表示されることを意味します。
-1 << 4は、「-1」のバイナリ値が4ビットシフトされることを意味します
「<<」は左シフト演算子です。-1 << 4は、-1を4ずつ左にシフトすることを意味します。-1は0xffffffffなので、0xfffffff0になります。
詳細については、wikihttp ://en.wikipedia.org/wiki/Bitwise_operationを参照してください。