ビットを 0 にする | Programming Place Plus C言語編 逆引き

トップページC言語編逆引き

このページの概要 🔗

以下は目次です。

目的 🔗

ある符号無し整数型の値を構成する複数のビットの中の、任意の位置のビットを 0 にしたいとします。

ビット演算は原則的に、符号無し整数型に対して使用します(第49章

ここでいう「任意のビット」は、特定の1つのビットでもいいですし、2ビット以上連続したり、飛び飛びであったりしてもいいものとします。たとえば、

といった具合です。

方法①(ビット積を使う) 🔗

あるビットを 0 にするには、ビット積(ビットAND)(第49章)を使います。

0 に “したくない” ビットにだけ “1” を立てた整数を用意し(これを BITS とします)、これとターゲットの整数とでビットAND を取れば実現できます。

ターゲットの整数 & BITS;

たとえば、ターゲットの整数を2進法で書いたとき “1100” で、偶数ビット(下から2つ目と最上位ビット)を 0 にしたいとします(つまり、“0100” にしたい)。この場合なら、BITS を “0101” にして、1100 & 0101 とすればいいことになります。

  1100
& 0101
------
  0100

実際に試してみます。

#include <stdio.h>

int main(void)
{
    unsigned char n1 = 0xf0;
    unsigned char n2 = 0x80;
    unsigned char n3 = 0x7f;


    // 一番上位のビットを 0 にする
    printf("%x\n", (n1 & 0x7f));
    printf("%x\n", (n2 & 0x7f));
    printf("%x\n", (n3 & 0x7f));
    puts("----");

    // 下位から数えて、3~7 ビット目の範囲を 0 にする
    printf("%x\n", (n1 & 0xc3));
    printf("%x\n", (n2 & 0xc3));
    printf("%x\n", (n3 & 0xc3));
    puts("----");

    // 奇数ビットすべてを 0 にする
    printf("%x\n", (n1 & 0xaa));
    printf("%x\n", (n2 & 0xaa));
    printf("%x\n", (n3 & 0xaa));
    puts("----");
}

実行結果:

70
0
7f
----
c0
80
43
----
a0
80
2a
----

桁が多いと分かりづらいので、ここでは unsigned char型を使って、8bit の符号無し整数型で試しています。もっと大きい型を使っても、ビットの数が増えるだけで、やり方はなんら変わりません。

また、結果だけが見たいので、変数の値を書き換えないようにしています。変数の値を変えたいのなら、(n1 & 0x7f) であれば n1 &= 0x7f; のようにすればいいです。


ところで、BITS を用意するときに、「0 に “したくない” ビットにだけ “1” を立てた整数」というのがやや分かりづらいかもしれません。実際、このようなビット列を用意するときは、「0 に “したい” ビットにだけ “1” を立てた整数」を書いて、そのビット否定を取るようにコーディングすることがあります。

つまり、最上位ビットを 0 にしたい場合に、0x7f を用意するのではなく、その反対である 0x80 を用意して、そのビット否定(第49章)をして ~0x80 とのあいだでビット積を取ります(n1 & ~0x80)。

この方法の場合、さきほどのサンプルプログラムは次のようになります。

#include <stdio.h>

int main(void)
{
    unsigned char n1 = 0xf0;
    unsigned char n2 = 0x80;
    unsigned char n3 = 0x7f;


    // 一番上位のビットを 0 にする
    printf("%x\n", (n1 & ~0x80));
    printf("%x\n", (n2 & ~0x80));
    printf("%x\n", (n3 & ~0x80));
    puts("----");

    // 下位から数えて、3~7 ビット目の範囲を 0 にする
    printf("%x\n", (n1 & ~0x3c));
    printf("%x\n", (n2 & ~0x3c));
    printf("%x\n", (n3 & ~0x3c));
    puts("----");

    // 奇数ビットすべてを 0 にする
    printf("%x\n", (n1 & ~0x55));
    printf("%x\n", (n2 & ~0x55));
    printf("%x\n", (n3 & ~0x55));
    puts("----");
}

実行結果:

70
0
7f
----
c0
80
43
----
a0
80
2a
----

ビット否定と組み合わせる方法を理解していると、ビットを 1 にする処理と、ビットを 0 にする処理とで、同じ BITS が使えるようになります。分かりやすくなりますし、便利でもあります。

void func(bool bit_on)
{
    if (bit_on) {
        target |= BITS;    // 1 を立てる
    }
    else {
        target &= ~BITS;   // 0 にする
    }
}


参考リンク 🔗


更新履歴 🔗



逆引きのトップページへ

C言語編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
X で ポストフォロー LINE で送る noteで書く
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー
先頭へ戻る