第9章 演習問題 解答例

9.4 ビット演算子

a9-4-1.c

任意の2つのunsigned int型で表すことのできる整数値を入力し、論理積(AND)、論理和(OR)、排他的論理和(XOR)を求めて表示してください。ただし、わかりやすいように16進数で表示してください。

/* a9-4-1.c */
#include <stdio.h>
#include <limits.h>

int main(void)
{
    unsigned a, b;

    printf("0 〜 %u の整数を2つ入力してください。\n", UINT_MAX);
    printf("> ");
    scanf("%u", &a);
    printf("> ");
    scanf("%u", &b);

    printf("%u(%#x) AND %u(%#x) = %#x\n", a, a, b, b, a & b);
    printf("%u(%#x) OR  %u(%#x) = %#x\n", a, a, b, b, a | b);
    printf("%u(%#x) XOR %u(%#x) = %#x\n", a, a, b, b, a ^ b);

    return 0;
}

入力するのはunsigned int型の整数なので、0〜UINT_MAX(P.307)を入力範囲としています。
なお、unsigned int型のintを省略してunsignedと記述しています。

[Back]

a9-4-2.c

任意のunsigned int型で表すことのできる整数値を入力し、そのビットパターンを表示する関数を作成してください。

 関数名 show_bit
 仮引数 unsigned dt:ビットパターンを表示する変数
 返却値 なし
/* a9-4-2.c */
#include <stdio.h>
#include <limits.h>

void show_bit(unsigned dt);

int main(void)
{
    unsigned a;

    printf("0 〜 %#x の16進数を入力してください。> ", UINT_MAX);
    scanf("%x", &a);

    show_bit(a);

    return 0;
}

/*** ビット表示関数 ***/
/*(引数)dt:表示データ */
void show_bit(unsigned dt)
{
    int i, len;

    len = sizeof(dt) * CHAR_BIT;
        
    printf("%#x ---> ", dt);
    for (i = len - 1; i >= 0; i--){
        putchar((dt >> i & 1U) ? '1' : '0' );
    }
    putchar('\n');
}

CHAR_BITは1バイトのビット数を表すマクロで、<limits.h>で定義されています。
show_bit関数は、各ビットを最下位までシフトし、1でANDを求めることによりビットのON/OFFを判定しています。1でANDを求めると最下位ビットだけを残してほかのビットを0にすることができます。なお、この判定には、条件演算子(P.144)を使用しています。

[Back]

a9-4-3.c

任意のunsigned int型で表すことのできる整数値を入力し、そのビットパターンを左右反転する関数を作成してください。なお、a9-4-2.cで作成したshow_bit関数を用いてビットパターンを表示してください。

 関数名 reverse_bit
 仮引数 unsigned dt:ビットパターンを反転する変数
 返却値 unsigned :反転した値
/* a9-4-3.c */
#include <stdio.h>
#include <limits.h>

unsigned reverse_bit(unsigned dt);
void show_bit(unsigned dt);

int main(void)
{
    unsigned a, b;

    printf("0 〜 %#x の16進数を入力してください。> ", UINT_MAX);
    scanf("%x", &a);
    show_bit(a);
    b = reverse_bit(a);
    show_bit(b);

    return 0;
}
/*** ビット反転関数 ***/
/*(引数)dt:データ (返却値)反転データ */
unsigned reverse_bit(unsigned dt)
{
    unsigned mask = 1U, bit, rb = 0U;
    int i, len;

    len = sizeof(dt) * CHAR_BIT;
    mask <<= len - 1;
    
    for (i = 0; i < len; i++) {
        bit = (dt & mask) ? 1U : 0U;
        bit <<= i;
        rb |= bit;
        mask >>= 1;
    }
    return rb;
}
/*** ビット表示関数 ***/
/*(引数)dt:表示データ */
void show_bit(unsigned dt)
{
    int i, len;

    len = sizeof(dt) * CHAR_BIT;
        
    printf("%#x ---> ", dt);
    for (i = len - 1; i >= 0; i--){
        putchar((dt >> i & 1U) ? '1' : '0' );
    }
    putchar('\n');
}

reverse_bitでは次のようにして左右ビットを反転しています。

1. マスク値(mask)にMSBが1のデータを作成。
2. maskを用いて対象ビットを作業用変数bitに取り出す。
3. bitを左右対称になるまでシフトする。
4. bitを返却用変数rbにビットORを求めて設定する。
5. maskを右へ1ビットシフトする。
6. 2〜5をMSBからLSBまで繰り返す。

※ LSB(最下位ビット):Least Significant Bit
  MSB(最上位ビット):Most Significant Bit

解説図

[Back]


Copyright© 2006,2012 Tomoko Sugawara. All Rights Reserved.