#1 変数を覗いてみよう (4) (98年11月7日 初版)

1.4 ビット単位論理演算  コンピュータの内部は、すべてのデータが0または1のビット並びで表現されます。 そして8ビットの並びを1バイトと呼びます。char型は1バイトを単位とする変数で、 これがもっとも小さなサイズのデータ型です。通常は、変数の操作はバイトレベルで プログラムを行いますが、プログラムからハードウェアを直接扱う場合などにはビッ トレベルの操作が必要になります。C/C++にはそのようなビット操作を行うためのビ ット演算子が用意されています。  以降では、このビット演算子を使って変数の中のビット並びを表示するプログラム を考えます。  ビット演算子には、ビットAND演算子(&)、ビットOR演算子(|)、ビットXOR 演算子(^)、ビットNOT演算子(〜)、左シフト演算子(<<)、右シフト演算子 (>>)があります。またビットXOR演算子のことをビット排他的OR演算子ともいい ますし、ビットNOT演算子のことをビット補数演算子ともいいます。  ビット演算子は、整数型と文字型に対してのみ使われる演算子です。また操作は、 一つ一つのビットに対してであることを頭に入れておきましょう。  まず、ビットAND演算子は2つのビットを比較して、共に1なら、結果は1で、 それ以外は0です。またビットOR演算子は、共に0なら、結果も0で、それ以外は 1となります。演算規則を表にすると。 ビット&演算子 ビットA ビットB ビットA & ビットB ------------------+----------------- 1 1 | 1 1 0 | 0 0 1 | 0 0 0 | 0 ------------------+----------------- ビット|演算子 ビットA ビットB ビットA | ビットB ------------------+----------------- 1 1 | 1 1 0 | 1 0 1 | 1 0 0 | 0 ------------------+-----------------  ビットAND(&)演算子と論理AND(&&)演算子と混同してはいけません。 ビット&は1つ1つのビットごとに演算を行いますが、&&は演算数全体に対して 1つの演算を行います。論理演算子&&の場合は、両方が真(非0)のとき、結果 は真(1)となります。ビット論理演算子&は、対応するビットの両方が1のとき、 対応するビットも1となります。 ビット論理演算と電気回路について  また、ビットXOR演算子^と、ビットNOT演算子〜は、 ビット^演算子 ビットA ビットB ビットA ^ ビットB ------------------+----------------- 1 1 | 0 1 0 | 1 0 1 | 1 0 0 | 0 ------------------+----------------- ビット〜演算子 ビットA 〜ビットA ---------+-------------- 1 | 0 0 | 1 ---------+-------------- XOR(^)演算子は、一方が1のときだけ、結果を1にします。NOT(〜)演算子は、 ビットを反転させます。  ビット&演算子の働きをみるための、プログラムを書いてみましょう。
// list01_05.cpp 
// ビット単位&演算の働き 
// 
#include <iostream.h> 
#include <iomanip.h> 

//10進数を2進数に変換してプリントする 
void dec2bin(int dec) 
{ 
    // dec2bin.cpp と同じもの 
} 

int main() 
{ 
    int i1, i2; 

    cout << "2つの整数を入力してください: "; 
        cin >> i1 >> i2; 

    cout << setw(19) << i1 << " = "; 
    dec2bin(i1); 

    cout << setw(19) << i2 << " = "; 
    dec2bin(i2); 

    cout << "(" << setw(7) << i1 << " & " << setw(7) << i2 << ") = "; 
    dec2bin( i1 & i2 ); 

    return 0; 
}
 ソースファイル
[実行結果]
C:\Source>lst01_05 
2つの整数を入力してください: 123 -123 
                123 = 00000000 00000000 00000000 01111011 
               -123 = 11111111 11111111 11111111 10000101 
(    123 &    -123) = 00000000 00000000 00000000 00000001 

C:\Source>lst01_05 
2つの整数を入力してください: 123 456 
                123 = 00000000 00000000 00000000 01111011 
                456 = 00000000 00000000 00000001 11001000 
(    123 &     456) = 00000000 00000000 00000000 01001000 

C:\Source>lst01_05 
2つの整数を入力してください: 12345 6789 
              12345 = 00000000 00000000 00110000 00111001 
               6789 = 00000000 00000000 00011010 10000101 
(  12345 &    6789) = 00000000 00000000 00010000 00000001 
[演習問題1.4]その他のビット演算子の機能を示すプログラムを書き、 実行してみなさい。  整数型のデータのビットパターンとビット演算子の様子をいろいろと試して みると、次のような関係に気付いたかもしれません。  ある整数 A とその反対符号の整数 -A との間には、 −A = 〜A + 1 という関係が成り立ちます。
// lst01_06.cpp 
// ビット単位&演算 
// 整数の正の数と負の数の関係 
#include <iostream.h> 

//10進数を2進数に変換してプリントする 
void dec2bin(int dec) 
{ 
    // dec2bin.cpp と同じ 
} 

int main() 
{ 
    int a; 

    cout << "整数を入力してください: "; 
    cin >> a; 

    cout << " a = " << a << " です。a と -a のビットパターンは:" 
         << endl; 

    cout << "     a = "; 
    dec2bin(a); 

    cout << "    -a = "; 
    dec2bin(-a); 

    cout << "\nビット演算子を使って、a から -a を作るには:\n"; 
    cout << "    ~a = "; 
    dec2bin(~a); 

    cout << "~a + 1 = "; 
    dec2bin( ~a + 1 ); 

    return 0; 
}
 ソースファイル
[実行結果]
C:\Source>lst01_06 
整数を入力してください: 0 
 a = 0 です。a と -a のビットパターンは: 
     a = 00000000 00000000 00000000 00000000 
    -a = 00000000 00000000 00000000 00000000 

ビット演算子を使って、a から -a を作るには: 
    ~a = 11111111 11111111 11111111 11111111 
~a + 1 = 00000000 00000000 00000000 00000000 

C:\Source>lst01_06 
整数を入力してください: 1 
 a = 1 です。a と -a のビットパターンは: 
     a = 00000000 00000000 00000000 00000001 
    -a = 11111111 11111111 11111111 11111111 

ビット演算子を使って、a から -a を作るには: 
    ~a = 11111111 11111111 11111111 11111110 
~a + 1 = 11111111 11111111 11111111 11111111 

C:\Source>lst01_06 
整数を入力してください: 123456 
 a = 123456 です。a と -a のビットパターンは: 
     a = 00000000 00000001 11100010 01000000 
    -a = 11111111 11111110 00011101 11000000 

ビット演算子を使って、a から -a を作るには: 
    ~a = 11111111 11111110 00011101 10111111 
~a + 1 = 11111111 11111110 00011101 11000000 
この関係を、−aはaの2の補数といいます。2の補数とは、すべてのビット を1から引き、その結果に1を加えることで求めます。a = 123456の2の補数 は、 11111111 11111111 11111111 11111111 -) a = 00000000 00000001 11100010 01000000 <--- [すべてのビットを1から引く] ------------------------------------------- 11111111 11111110 00011101 10111111 <--- ビットが反転している +) 00000000 00000000 00000000 00000001 <----[1を加える] ------------------------------------------- 11111111 11111110 00011101 11000000 <---- これは −a つまり、すべてのビットを1から引くことは各ビットを反転することで、これ はまさにビットNOT演算です。すでに述べたように、ビットNOT演算子のことを ビット補数演算子ともいいます。そして、この各ビットを反転したものを1の 補数といいます。 (注意)int型の内部表現は、左端の1ビット目が、その数の符号 を表すようになっています。これを符号ビットと呼び、正の数は0、 負の数は1となっています。したがって値そのものは31ビットで 表現されます(int型が4バイトの場合)。

| 目次 | 前のページ | 次のページ |

Copyright(c) 1998,1999 Yamada, K