[解決済み】ビットシフト(bit-shift)演算子とは、どのようなもので、どのように機能するのですか?
質問
私は暇な時にC言語を学ぼうとしているのですが、他の言語(C#、Javaなど)でも同じ概念(同じ演算子であることも多い)があります ...
気になるのは、核心的なレベルでは、ビットシフト(
<<
,
>>
,
>>>
は何をするのか、どんな問題を解決できるのか、そしてどんな問題が潜んでいるのか。言い換えれば、ビットシフトの良さをすべて網羅した、まったくの初心者向けのガイドブックです。
どのように解決するのか?
ビットシフト演算子は、その名の通りビットシフトを行う演算子です。 ビットをシフトするのです。 ここでは、さまざまなシフト演算子について簡単に(あるいはあまり簡単に)紹介します。
演算子
-
>>
は算術(または符号)右シフト演算子です。 -
>>>
は、論理(または符号なし)右シフト演算子です。 -
<<
は左シフト演算子で、論理シフトと算術シフトの両方のニーズに対応しています。
これらの演算子はすべて、整数値に対して適用することができます (
int
,
long
もしかしたら
short
と
byte
または
char
). いくつかの言語では,シフト演算子を
int
は自動的にオペランドのサイズを変更し
int
.
なお
<<<
は冗長になるので演算子ではありません。
また、以下の点にも注意してください。
CとC++は右シフト演算子を区別していない
. これらは
>>
演算子があり、右シフトの動作は符号付き型に対する実装定義です。 残りの回答は、C# / Javaの演算子を使用しています。
(GCCやClang/LLVMを含むすべての主流のCとC++の実装で。
>>
の符号付き型は算術演算です。 これを前提としたコードもありますが、標準が保証しているものではありません。 これは
未定義
しかし、この規格では、実装が何らかの形でそれを定義することを要求しています。 ただし,負の符号付き数値の左シフトは
は
未定義の動作 (符号付き整数のオーバーフロー) です。 したがって、算術的な右シフトが必要でない限り、通常は符号なし型でビットシフトを行うのがよいでしょう)。
左シフト(<<)
整数は、メモリ上ではビットの連続として保存されます。 例えば、6という数字は32ビットの
int
となります。
00000000 00000000 00000000 00000110
このビットパターンを1つ左にずらすと(
6 << 1
の場合、12という数字になります。
00000000 00000000 00000000 00001100
見ての通り、桁は1つ左に移動し、右側の最後の桁は0で埋め尽くされています。 また、左シフトは2の累乗と同じであることに注意してください。
6 << 1
は、次のように等価です。
6 * 2
であり、かつ
6 << 3
は、以下のものと同等です。
6 * 8
. 優れた最適化コンパイラは、可能な限り、乗算をシフトに置き換えます。
非円形シフト
なお、これらは
ではなく
循環シフト この値を左に1つずらすと(
3,758,096,384 << 1
):
11100000 00000000 00000000 00000000
の結果は、3,221,225,472 となります。
11000000 00000000 00000000 00000000
端にずれた桁は失われます。 回り込みはしません。
論理右シフト(>>>)
論理的右シフトは、左シフトの逆です。 ビットを左に移動させるのではなく、単純に右に移動させます。 例えば、数字の12をシフトさせる場合です。
00000000 00000000 00000000 00001100
を1つ右に移動させる (
12 >>> 1
を実行すると、元の6に戻ります。
00000000 00000000 00000000 00000110
つまり、右にシフトすることは2の累乗で割ることと同じであることがわかります。
ロストビットが消える
しかし、シフトは失われたビットを再生することはできません。 例えば、このパターンをシフトさせると
00111000 00000000 00000000 00000110
を左の4つの位置(
939,524,102 << 4
を使用すると、2,147,483,744 になります。
10000000 00000000 00000000 01100000
で、後ろにずれていく(
(939,524,102 << 4) >>> 4
となり、134,217,734となります。
00001000 00000000 00000000 00000110
一度失ったビットは、元の値には戻りません。
算術右シフト(>>)
算術右シフトは論理右シフトと全く同じですが、0を詰めるのではなく、最上位ビットを詰めます。 これは、最上位ビットが 符号 ビット、つまり正負の数を区別するためのビットです。 最上位ビットでパディングすることで、算術的右シフトは符号を保持することができます。
例えば、このビットパターンを負の数と解釈した場合。
10000000 00000000 00000000 01100000
という数字は、-214万7,483,552となります。 これを算術シフト(-2,147,483,552 >> 4)で右に4ポジションシフトすると、こうなります。
11111000 00000000 00000000 00000110
または、-134,217,722という数字です。
つまり、論理的な右シフトではなく、算術的な右シフトを使うことで、負の数の符号を維持していることがわかります。 そしてまた、2の累乗による除算を行っていることがわかる。
関連
-
[解決済み] 言語バインディングとは何ですか?
-
[解決済み] C言語のシフト演算子(<<, >>)は算術演算子ですか、論理演算子ですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] Pythonにはなぜ++と--の演算子がないのですか?
-
[解決済み] ランタイムとコンパイルタイム
-
[解決済み] セッションとは何ですか?どのように機能するのですか?
-
[解決済み】|と||や演算子の違いは何ですか?
-
[解決済み】C言語でシフト演算子を使った掛け算・割り算は実は速い?
-
[解決済み】GOTOはまだ有害と考えられている?[クローズド]
-
[解決済み] ボクシングとアンボクシング、そのトレードオフとは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] カスタムクラス」の意味を教えてください。
-
[解決済み] 並行処理と並列処理の違いは何ですか?
-
[解決済み] 点から線分までの最短距離
-
[解決済み】キャメルケースの頭字語【終了しました
-
[解決済み】GOTOはまだ有害と考えられている?[クローズド]
-
[解決済み】ビット演算子の実際の使用例【クローズド
-
[解決済み] イーガーローディングとは何ですか?
-
[解決済み] Javaでシフト演算子はどのように動作するのですか?[重複しています]。
-
[解決済み] プログラミングにおける "Context "という言葉?[クローズド]
-
[解決済み] お気に入りの(賢い)防御的プログラミングのベストプラクティス【非公開