C言語のビットをシフト演算子で操作する【<<, >>, 左シフト、右シフト】
- 作成日: 2022-06-06
- 更新日: 2023-12-25
- カテゴリ: C言語
C言語のビットをシフト演算子で操作する
今回はC言語のビット演算のうち、シフト演算子について解説します。
変数などの持つ値のビット列を操作することをビット演算と言います。
そのビット演算の中でビットを左にシフトしたり右にシフトしたりする演算をシフト演算と言います。
この記事を読めばビット列へのシフト演算がわかります。
ビット演算の理解を深めたい方におすすめです。
関連記事
目が覚めるC言語のdo-while文の使い方【ループ処理、初心者向け】
明快!C言語のcontinue文の使い方
君はまだC言語のdefineのすべてを知らない【マクロ、プリプロセス】
目が覚めるC言語のdo-while文の使い方【ループ処理、初心者向け】
明快!C言語のcontinue文の使い方
君はまだC言語のdefineのすべてを知らない【マクロ、プリプロセス】
ビット列を表示する関数を作る
今回はシフト演算の理解のために変数のビット列を出力する関数を作ります。
この関数もシフト演算を使ってます。
#include <stdio.h>
void show_bits(int var) {
int nbytes = sizeof(var);
int nbits = nbytes * 8;
printf("%4d -> ", var);
for (int i = nbits - 1; i >= 0; i -= 1) {
int n = var >> i;
if (n & 1) {
putchar('1');
} else {
putchar('0');
}
if (i > 0 && i % 4 == 0) {
putchar(' ');
}
}
puts("");
}
int main(void) {
show_bits(0);
show_bits(1);
show_bits(8);
show_bits(32);
show_bits(64);
show_bits(255);
show_bits(256);
return 0;
}
↑のコードを実行すると↓の結果になります。
0 -> 0000 0000 0000 0000 0000 0000 0000 0000
1 -> 0000 0000 0000 0000 0000 0000 0000 0001
8 -> 0000 0000 0000 0000 0000 0000 0000 1000
32 -> 0000 0000 0000 0000 0000 0000 0010 0000
64 -> 0000 0000 0000 0000 0000 0000 0100 0000
255 -> 0000 0000 0000 0000 0000 0000 1111 1111
256 -> 0000 0000 0000 0000 0000 0001 0000 0000
この関数の原理については今回は理解しなくてもOKです。
シフト演算子の理解とはまた違うベクトルの話になるからです。
しかし興味がある人のために簡単に解説します。
show_bits()
関数では引数var
のビット数を最初に計算します。
sizeof(var)
で変数var
のバイト数、それに8をかけてビット数にします。
ループを回しながらvar
をカウント変数で右シフトします。
こうするとビット列がカウント変数分だけ右に移動します。
その移動したビット列(変数n
)を1
でANDを取ります。
仮にn
の最下部のビットが立っていたらこの式は真になります。
最下部のビットが立っていたら1
と出力し、立っていなかったら0
と出力します。
ビット列の桁をずらしながらすべてのビットでこのようにしていきます。
そうすると最終的にvar
の各ビット1
と0
で表現されます。
4ビットごとに空白スペースを入れて出力を見やすくしています。
最後に改行を入れて完了です。
右シフトについて学ぶ
シフト演算の内、変数のビット列を右にシフトする演算を「右シフト演算」と言います。
この演算を行うとビット列を右にずらせます。
式の書き方は↓です。
値 >> シフトする数
左の値には即値や変数を起きます。
>>
が右シフト演算子ですが、右にさきっちょが向いてますね。
右シフト演算子はビット列を右にずらしますが、>>
の右側にはいくつずらすかその数を書きます。
先ほどshow_bits()
関数を使って右シフトの結果を見てみます。
int n = 8;
show_bits(n);
n = n >> 1;
show_bits(n);
変数n
に8
を代入して、それを1
だけ右シフトしています。
n >> 1
が右シフト演算です。
そうすると結果は↓のようになります。
8 -> 0000 0000 0000 0000 0000 0000 0000 1000
4 -> 0000 0000 0000 0000 0000 0000 0000 0100
整数8
は右から4つ目のビットが立っています。
これはビット列では1000
ですが、これは2進数になります。
10進数に直すと1000
は8
になります。
それで1
ビットだけ右シフトした変数は整数では4
になります。
値が半分になっていますね。
そしてビット列を見ると0100
になっていて、1
のビットが右に1つずれているのがわかります。
これは右シフト演算でビット列を右にシフトしたからです。
では次は整数8
を2
ビット右にシフトしてみます。
n = 8;
show_bits(n);
n = n >> 2;
show_bits(n);
8 -> 0000 0000 0000 0000 0000 0000 0000 1000
2 -> 0000 0000 0000 0000 0000 0000 0000 0010
そうすると今度は8
が2
になりました。
ビット列を見ると1000
が0010
になっています。
これは右シフト演算で2だけ右にシフトしたからです。
1だけ右にシフトすると8
が4
になり1/2
になりました。
そして2だけ右にシフトすると8
が2
になり1/4
になりました。
では3だけ右シフトするとどうなるでしょうか?
n = 8;
show_bits(n);
n = n >> 3;
show_bits(n);
8 -> 0000 0000 0000 0000 0000 0000 0000 1000
1 -> 0000 0000 0000 0000 0000 0000 0000 0001
そうすると今度は8
が1
になりました。
1/8
ですね。
ビット列は1000
から0001
です。
こういう感じで右シフト演算は値を1/2
, 1/2
...にしていきます。
ビット列は右に1つずつずれます。
ビット列が右に1つずれると値は1/2
になる、と覚えておくとわかりやすいと思います。
左シフトについて学ぶ
右シフトは値を1/2
, 1/2
...にしていきました。
左シフトはその逆で値を2
倍、2
倍にしていきます。
左シフト演算子の式の書き方は↓です。
値 << シフトする数
show_bits()
でビット列を見てみましょう。
n = 8;
show_bits(n);
n = n << 1;
show_bits(n);
8 -> 0000 0000 0000 0000 0000 0000 0000 1000
16 -> 0000 0000 0000 0000 0000 0000 0001 0000
そうすると↑のように8
の値が16
になります。
ビット列は0000 1000
が0001 0000
になりました。
こういう感じで左シフトはビット列を左にシフトします。
ビット列が1だけ左にシフトするとその値は倍になります。
では次は2
だけ左シフトしてみます。
n = 8;
show_bits(n);
n = n << 2;
show_bits(n);
そうすると結果は↓になります。
8 -> 0000 0000 0000 0000 0000 0000 0000 1000
32 -> 0000 0000 0000 0000 0000 0000 0010 0000
整数の8
が32
になりました。
4倍になってますね。
ビット列は左に2だけシフトしています。
このように左シフトは値を2
倍、2
倍...にしていきます。
そしてビット列は左にずれていきます。
ビット演算はビット列で視覚的に確認すると理解しやすいです。
よくわからなくなったらビット列を確認しましょう。
代入シフト演算子
右シフト演算子と左シフト演算子には親戚がいます。
それは↓の演算子です。
>>=
<<=
これらの演算子は変数に対して直接シフト演算を行います。
つまり変数の値を操作します。
たとえば↓のようにすると
n = 8;
n >>= 1;
show_bits(n);
n <<= 2;
show_bits(n);
結果は↓のようになります。
4 -> 0000 0000 0000 0000 0000 0000 0000 0100
16 -> 0000 0000 0000 0000 0000 0000 0001 0000
n >>= 1;
はn = n >> 1;
と同じ結果になります。
n <<= 2;
はn = n << 2;
と同じ結果です。
これは足し算の+=
演算子などと同じ感じの演算子です。
おわりに
今回はC言語のビット列をシフトする演算子を解説しました。
ビット演算は上級者向けの演算ですが慣れておくと意外に便利です。
理解が難しくなったらビット列を確認するクセをつけておくと吉です。
🦝 < ようこそ、ビットを操作するものよ
🐭 < うーん、ハカー