C 言語でのビットシフト操作の使用
胡金庫
2023年10月12日
この記事では、C 言語でビットシフト演算を使用する方法をいくつか説明します。
C 言語で数値を左にシフトするために <<
演算子を使用する
ビット単位のシフト演算はすべてのプログラミング言語に含まれており、整数オペランドの各ビットを指定された数だけ再配置します。これらの演算の効果をよりよく示すために、以下の例では、与えられた整数の 2 進表現を表示する binary
という名前の関数を用いています。この関数は 32 ビットの整数値を扱うためにのみ実装されていることに注意してください。以下のコード例は、左シフトを 2つの位置で行い、それに応じて数値表現を表示します。
#include <stdio.h>
#include <stdlib.h>
void binary(unsigned n) {
unsigned i;
for (i = 1 << 31; i > 0; i /= 2) (n & i) ? printf("1") : printf("0");
}
int main(int argc, char *argv[]) {
int n1 = 123;
binary(n1);
printf(" : %d\n", n1);
n1 <<= 2;
binary(n1);
printf(" : %d\n", n1);
exit(EXIT_SUCCESS);
}
出力:
00000000000000000000000001111011 : 123
00000000000000000000000111101100 : 492
C 言語で左シフトを使用して 2つの整数を複数指定する
左シフト演算を利用して 2 倍の乗算を実装することで、ハードウェア上での効率化を図ることができます。左シフトの場合、算術シフトと論理シフトの違いはないことに注意してください。与えられた整数の単一位置シフトは乗算になります。
#include <stdio.h>
#include <stdlib.h>
void binary(unsigned n) {
unsigned i;
for (i = 1 << 31; i > 0; i /= 2) (n & i) ? printf("1") : printf("0");
}
int main(int argc, char *argv[]) {
int n1 = 123;
printf("%d\n", n1);
n1 <<= 1;
printf("%d x2\n", n1);
exit(EXIT_SUCCESS);
}
出力:
492
984 x2
右シフト - C での算術シフトと論理シフトの違い
符号付き整数と符号なし整数は内部では異なる表現をしていることに言及しておくべきです。すなわち、signed
の整数は 2 の補数として実装されます。その結果、負数の最上位ビットは符号ビットと呼ばれる 1
であるのに対し、正の整数は通常通り 0
から始まる。したがって、負の数を論理的に右にずらすと、符号を失って正の整数が得られることになります。つまり、論理シフトと算術シフトを区別する必要があり、後者の方が最上位ビットを保持することになります。概念の違いはあっても、C 言語では演算子を区別することはできません。また、ハードウェアの実装で定義されているため、C 標準では動作を指定していません。次の出力例に示すように、基礎となるマシンは算術シフトを行い、整数の負の値を保存しています。
#include <stdio.h>
#include <stdlib.h>
void binary(unsigned n) {
unsigned i;
for (i = 1 << 31; i > 0; i /= 2) (n & i) ? printf("1") : printf("0");
}
int main(int argc, char *argv[]) {
int n2 = -24;
binary(n2);
printf(" : %d\n", n2);
n2 >>= 3;
binary(n2);
printf(" : %d\n", n2);
exit(EXIT_SUCCESS);
}
出力:
11111111111111111111111111101000 : -24
11111111111111111111111111111101 : -3