サイトマップ / C言語講座>出入り口>総目次>目次:ビット演算>整数の内部表現
[ビット毎の論理積と論理和]←このソース→[整数の取り得る範囲]
/* 今回は、ビット反転 (演算子: ~) や、ビット毎の排他的論理和 ( XOR ) ( 演算子: ^) について学びます。
ビットを反転させるということは、あるビットが 0 ならば 1 に、1 なら 0 にするということです。ビットを反転させるということを、「 1 の補数を求める」といいます。下記に signed char 型の整数の例を示します。
10進表示 | ビットパターン | |||||||
2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
ビット反転すると | ||||||||
-3 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
2 が - 3 になりました。コンピュータでマイナスの値を表すにはどうしているのでしょう。以下に 0 から値を増やした時のビットパターンを示します。
10進表示 | ビットパターン | |||||||
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
3 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
途 中 省 略 | ||||||||
126 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
127 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
-128 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
-127 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
-126 | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
途 中 省 略 | ||||||||
-3 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
-2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
-1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
3 と - 3 のビットパターンを比較してみます。
10進表示 | ビットパターン | |||||||
3 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |
-3 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 |
3 の各ビットを反転させたものを下記に示します。
10進表示 | ビットパターン | |||||||
~3 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 |
~3 の第 0 ビットを立てたものが、- 3 です。つまり、ビットを反転して、1 を加えれば、マイナスの数になります。この操作のことを、「 2 の補数を求める」といいます。コンピュータはこのような方法で、マイナスの値を内部表現しています。
符号付きの整数は最上位ビット ( MSB ) が1ならばマイナスの値です。符号なし整数は最上位ビットも数を表すのに使います。
前回はビット毎の論理和と論理積について学びました。これ以外にも、ビット毎の排他的論理和 ( XOR 演算記号:^)があります。ビット毎の排他的論理和とは、1 と 1 なら 0 に、1 と 0 なら 1 に、0 と 0 なら 0 になります。今回のソースプログラムでは、ビットを 0 にするのに使っています。
今回のソースプログラムで、ビットパターンを表示する関数がでてきます。短い関数ですが、その中に下記のコードがあります。
printf("%d", (c >> i) & 0X01);
(c >> i) はi ビット右へシフトさせます。その結果、第 i ビットが第 0 ビットに来ます。0X01 は第 0 ビットのみが 1 なので、論理積を取ることにより、i ビット目を取り出すことができます。
後は、ソースプログラム中のコメントをごらん下さい。プログラムの実行結果も、良く見て下さい。 */
#include <stdio.h> #define BIT1 0X02 /* 第 1 ビットのみ 1 */ #define BIT7 0X80 /* 第 7 ビットのみ 1 */ void ShowBit(signed char c); void main(void); /* ビットパターンを表示する */ void ShowBit(signed char c) { int i; for ( i = 7; i >= 0; i--) /* i ビット目を表示する */ printf("%d", (c >> i) & 0X01); } void main(void) { signed char c = 0; int i; c = ~c; /* 全ビットを立てる */ c = c ^ BIT7; /* 第 7 ビットを 0 にする */ c = c ^ BIT1; /* 第 1 ビットを 0 にする */ for (i = 0; i < 6; i++) { ShowBit(c); /* ビットパターンを表示して */ printf(": %4d\n", c++); /* その値も表示 */ } } |
/* 今回はビットパターンを表示する関数がでてきました。これをペーパーテストの時などに、手計算で行うにはどうしたら良いでしょう。下記に示すのは10進数36のビットパターンを求めた例です。
計 算 | 余り |
36 ÷ 2 = 18 | 0 |
18 ÷ 2 = 9 | 0 |
9 ÷ 2 = 4 | 1 |
4 ÷ 2 = 2 | 0 |
2 ÷ 2 = 1 | 0 |
1 ÷ 2 = 0 | 1 |
順次2で割っていき、余りの列の数字を下から順に並べます。
100100
この場合 8 ビットなので、数字の数が 8 に満たなければ、足りない分頭に 0 を付けます。
00100100
では、2 進数を 16 進数に変換するにはどうしたら良いでしょう。
2進数 | 16進数 | 2進数 | 16進数 |
0000 | 0 | 1000 | 8 |
0001 | 1 | 1001 | 9 |
0010 | 2 | 1010 | A |
0011 | 3 | 1011 | B |
0100 | 4 | 1100 | C |
0101 | 5 | 1101 | D |
0110 | 6 | 1110 | E |
0111 | 7 | 1111 | F |
4 ビットの数に対する上記の変換をする表を作ります。
次に下の桁から 4 桁ずつ区切ります。
1101001 -> 110 1001
4 桁に満たなければ、頭に 0 を付けます。
110 1001 -> 0110 1001
上の表に従って、変換します。
0110 1001 -> 0X69
16 進数を 2 進数に変換するにも、上の変換表で簡単にできます。 */
[ビット毎の論理積と論理和]←このソース→[整数の取り得る範囲]
/* (C) 2000- YFプロ. All Rights Reserved. */ 提供:C言語講座−それ自体コンパイルできる教材を使った講座です−