(13.1.1) 英語では bitwise operators と呼ぶ。 加減乗除よりも速いのが特長である。
(13.1.2) コンピュータの中は「0 と 1 だけの世界」などと言われる。 「0 か 1 か」の情報だけを格納できる“もの”――うまく言えない――を 1 ビット (bit) という。 いままで整数を格納してきた int 型変数は、 いま使っている C コンパイラでは、32 個のビットを並べて用い、 二進法で格納している。 よって、格納できる整数は 0 から 232-1 まで、 となりそうだが、およそ半分は負の整数にあてているので、 -231 から 231-1 までである。 負の数をどのように格納するかは、ここでは省略する。
(13.1.3) 簡単のため、下の 8 ビットだけを書いて説明する。 ここでは、0 を偽、1 を真とする。 おのおののビットごとに、「かつ」、「または」、「排他的または」 の計算をおこなう演算子がある。
それらをビットごとに計算するので、次のようになる。
|
|
|
C 言語での記号は、上の表の左下のますに書いた。 「^」は、マイナスのキーの右どなりにある。 「かつ」は and, 「または」は or, 「排他的または」は xor と呼ぶこともある。 xor は exclusive or の“略”である。
(13.1.4) ほかに、「左シフト」「右シフト」「否定」の演算子がある。 それぞれ、「<<」、「>>」、「~」 と書く。 「~」は、シフトキーを押しながら「^」のキーを打つ。 「a << 2」は、a のビット列を左に 2 だけずらしたものである。 左にはみ出した 2 ビットは消える。 右には、0 が二つ、はいる。 「a >> 2」は、a のビット列を右に 2 だけずらしたものである。 右にはみ出した 2 ビットは消える。 左には、0 が二つ、はいる。 ただし、a が負であった場合については、ここではふれない。 「~a」は、a のビットをすべて反転したものである。 つまり、0 であったビットは 1 に、1 であったビットは 0 になる。
(13.1.5) 十進で入力した整数を二進で出力するプログラム。 「&」と「>>」を使っている。
#include <stdio.h> int main() { int n, mask; printf("0 以上、255 以下の整数を入力してください.\n"); scanf("%d", &n); for (mask = 128; mask != 0; mask = mask >> 1) { if ((n & mask) != 0) { printf("1"); } else { printf("0"); } } printf("\n"); }
注意:「if (n & mask != 0)」と書くと別の意味になる。このへんはややこしい。
128 は、二進の 10000000 である。 この数と「&」をとって 0 でないということは、 下から 8 ビットめが 1 であることを意味する。 この 128 を、「>>」を使って右にシフトしてゆく。
(13.1.6) 二進表記の整数を十進で出力するプログラム。 「|」と「<<」を使っている。
#include <stdio.h> int main() { int n, r, mask; printf("二進で正の数を入力してください.\n"); scanf("%d", &n); r = 0; mask = 1; for ( ; n != 0; n = n/10) { if (n % 10 != 0) { r = r | mask; } mask = mask << 1; } printf("%d\n", r); }
0 と 1 だけが打ち込まれると想定している。 (0 でない数字は 1 とみなされる。)
mask は 1 から始まって、1 ビットずつ左にシフトしてゆく。 r と mask の「|」をとったものを r に代入するということは、 r のそのビットを 1 に変えることを意味する。
(13.2.1) 二つの int 型を引数にとり、それらの和を返す関数 int add(int x, int y) を、 ビットごとの演算子と代入「=」と比較「!=」だけを使って書け。 くり返しの for も使ってよい。
(13.2.2) ヒント:「繰り上がり」を入れておく変数が必要になると思う。 英語では carry と言うらしいので、名前は c でどうだろうか。
(13.2.3) 二つの引数が 0 以上の場合に正しく動くように書けばよい。 その関数に負の数を引数として渡すと、 ここのパソコンでは正しく計算するようである。