C++サンプル集

【第1部】C言語(K&R検証)編

0015.ビット演算

 K&Rでは第2章:データ型・演算子・式に記述されています。ビットごとの論理演算子のところで、getbits()関数という、変数の各ビットの状態を調べる関数が紹介されていますが、ちょっとここでは省略します。
 代わりとして、よく使用されるビット演算を紹介します。

ソース紹介

CPPファイルに記述
#include <iostream>
#include <cstdio>
using namespace std;

#define FLG_A   0x0001
#define FLG_B   0x0002
#define FLG_C   0x0004
#define FLG_D   0x0008
#define FLG_E   0x0010
#define FLG_F   0x0020
#define FLG_G   0x0040
#define FLG_H   0x0080

int main()
{
    unsigned int a = FLG_B | FLG_F;
    if (a & FLG_B) {
        cout << "FLG_Bが有効です" << endl;
    }
    else {
        cout << "FLG_Bが無効です" << endl;
    }
    a ^= FLG_B;
    if (a & FLG_B) {
        cout << "FLG_Bが有効です" << endl;
    }
    else {
        cout << "FLG_Bが無効です" << endl;
    }
    return 0;
}
出力
FLG_Bが有効です
FLG_Bが無効です

サンプル説明

 ここでは、ビット演算フラグとして使用される例を紹介します。
#define FLG_A   0x0001
#define FLG_B   0x0002
#define FLG_C   0x0004
#define FLG_D   0x0008
#define FLG_E   0x0010
#define FLG_F   0x0020
#define FLG_G   0x0040
#define FLG_H   0x0080
 は、各ビットごとのフラグです。
 main()関数では
    unsigned int a = FLG_B | FLG_F;
 とFLG_B と FLG_F立てて(有効にして)います。これを検証するには
a & FLG_B
 のように & 演算子で行います。
 そのフラグをクリアするには
    a ^= FLG_B;
 のようにします。
 続いて、ビットシフトのサンプルを紹介します。

ソース紹介

CPPファイルに記述
#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
    unsigned int n = 567;
    n <<= 3; //この結果、n == 4536 になる。(567 * 8)
    cout << n << endl;
    n = 56;
    n >>= 1; //この結果、n == 28 になる。(56 / 2)
    cout << n << endl;
    n = 2587;
    n >>= 3; //この結果、n == 323 になる。(2587 / 8)
    cout << n << endl;
    return 0;
}
出力
4536
28
323

サンプル説明

 左に1つビットシフトすると、2倍にするという意味になります。
 2つだと4倍です、この例では
    n <<= 3;
 と、3個ビットシフトしてますので8倍です。
 右にビットシフトはこの逆です。右に1つビットシフト2分の12つで4分の13つで8分の1です。整数での計算ですから、余りが出た場合は、切り捨てられます。
 もう一つ紹介します。今度はK&Rのビット操作の関数をC++で書き直したものです。

ソース紹介

CPPファイルに記述
#include <iostream>
#include <cstdio>
using namespace std;

/*
xの中の1であるビットを数える
*/
int bitcount(unsigned int x) {
    int b;
    for (b = 0; x != 0; x >>= 1) {
        if (x & 01) {
            b++;
        }
    }
    return b;
}

/*
ビットカウントのテスト
*/
int main()
{
    cout << "56: " << bitcount(56) << endl;
    cout << "0X1b: " << bitcount(0X1b) << endl;
    return 0;
}
出力
56: 3
0X1b: 4

サンプル説明

 bitcount()関数内の
    for (b = 0; x != 0; x >>= 1) {
 の条件式は重要です。unsigned intの場合、右シフトすると、左端のビットは 0 で埋められます。
 ですから、右にどんどんシフトしていくと、最終的に 0 になります。この特性を利用して、forの条件式を記述しています。

K&Rでの記述

 元になったbitcount()関数第2章:データ型・演算子・式に記述されています。代入演算子と式の説明のところです。