★ビット演算(論理演算1)★


ここからはビット演算について説明します。

ビット演算とは、2進数を使った計算方法の1種です。

もしかすると「なぜ今頃?」と思われた方もいるかも知れません。

この講座は「プログラムが作れるようになる事」を主眼に置いています。

これまでのプログラムでは、論理演算は必要ありませんでしたので、説明を後回しにしました。

※多くのC言語のテキストなどでは、最初の方に書いてありますね。

※2進数を覚えていない方は「基数変換」などのコラムで再度確認してみてください。


論理演算には次の4種類があります。

日本語英語記号備考
論理積and&
論理和or|shiftキーを押しながら¥
排他的論理和xor 又は eor^¥の左
否定not~shiftキーを押しながら^

まずはそれぞれの考え方から説明しましょう。


1.論理積


論理積(and, &)

  1と1をand演算すると1になります。

  1と0をand演算すると0になります。

  0と0をand演算すると0になります。

4ビットで表してみると、

<論理積>

    1010
  & 1100
  ------
    1000

となります。


2.論理和


論理和(or, |)

  1と1をor演算すると1になります。

  1と0をor演算すると1になります。

  0と0をor演算すると0になります。

4ビットで表してみると、

<論理和>

    1010
  | 1100
  ------
    1110

となります。


3.排他的論理和


排他的論理和(xor又はeor, ^)

  1と1をxor演算すると0になります。

  1と0をxor演算すると1になります。

  0と0をxor演算すると0になります。

4ビットで表してみると、

<排他的論理和>

    1010
  ^ 1100
  ------
    0110

となります。


4.否定


否定だけは、単項演算(++や−−と同じ)です。

否定(not, 〜)

  1をnot演算すると0になります。

  0をnot演算すると1になります。

4ビットで表してみると、

<否定>

  ~ 1010
  ------
    0101

となります。


C言語での使い方


C言語で論理演算を使用する際には、2進数が使えませんので16進数を使う事が多いです。

桁が多いと分かりづらいので、一番小さいサイズの型「char型:8ビット」を使って作ります。

論理演算の前に、まずは注意すべき点から説明します。

まずはこのプログラムの実行結果を考えてみてください。

<sample program 177-01>

#include <stdio.h>

int main(void)
{
    char data1 = 0xAF;

    printf("data1 = %X\n", data1);

    return 0;
}

<実行結果>









































解答です。

data1 = FFFFFFAF
続行するには何かキーを押してください・・・

考えた結果と同じだったでしょうか?

char型は8ビットの変数のはずです。

  0xAF

は、2進数で表すと、

  1010 1111

だと、「基数変換」の最後で書きました。

しかし、結果を2進数で表すと、

  1111 1111 1111 1111 1111 1111 1010 1111

8ビットではなく、32ビットで表示されました。


どうしてなのでしょうか?

とりあえず、10進数で表示してみましょう。

<sample program 177-02>

#include <stdio.h>

int main(void)
{
    char data1 = 0xAF;

    printf("data1 = %d\n", data1);

    return 0;
}

<実行結果>

data1 = -81
続行するには何かキーを押してください・・・

なぜか、マイナスの数値が表示されました。

2進数でのマイナスの表現は、「マイナスの表現」で書きました。

「2の補数」という考え方では、最上位ビット(2進数を横に書いて一番左のビット)は符号がマイナスということを表しています。

ですから、

  0xAF

は、

  1010 1111

最上位ビットが1なので、マイナスの値として認識されます。

細かく書くと↓の通りで、

   1の位 が 1個 =    1
   2の位 が 1個 =    2
   4の位 が 1個 =    4
   8の位 が 1個 =    8
  16の位 が 0個 =    0
  32の位 が 1個 =   32
  64の位 が 0個 =    0
−128の位 が 1個 = −128

合計すると、「−81」です。


よく見るとプログラムをコンパイルした時に、警告が出ています。

  warning C4309: '初期化中': 定数値が切り捨てられました。

直接的な意味は分かりづらいですが、何か問題がある事は分かります。

  0xAF

を、マイナスの値ではなく、単純なビット列として扱うにはこれではダメということです。


マイナスの値として認識されているのは、char型が「符号あり」の型だからです。

変数について」で説明しました。

整数型を使う際には、「符号あり」か「符号なし」かをプログラマが選べるようになっています。

ビット列を扱う際には、「符号なし」を選択することが重要です。

では、プログラムを書き換えてみましょう。

<sample program 177-03>

#include <stdio.h>

int main(void)
{
    unsigned char data1 = 0xAF;

    printf("data1 = %d\n", data1);

    return 0;
}

<実行結果>

data1 = 175
続行するには何かキーを押してください・・・

コンパイル時の警告も無くなっていますよね。


「符号なし」になりましたから、

   1の位 が 1個 =   1
   2の位 が 1個 =   2
   4の位 が 1個 =   4
   8の位 が 1個 =   8
  16の位 が 0個 =   0
  32の位 が 1個 =  32
  64の位 が 0個 =   0
 128の位 が 1個 = 128

合計すると、「175」です。

では、16進数で表示し直します。

<sample program 177-04>

#include <stdio.h>

int main(void)
{
    unsigned char data1 = 0xAF;

    printf("data1 = %X\n", data1);

    return 0;
}

<実行結果>

data1 = AF
続行するには何かキーを押してください・・・

やっと論理演算を使う準備が出来ました。

では、最後に論理積を使ってみましょう。

<sample program 177-05>

#include <stdio.h>

int main(void)
{
    unsigned char data1 = 0xAF;

    unsigned char data2 = 0xCC;

    unsigned char result = data1 & data2;

    printf("result = %X\n", result);

    return 0;
}

<実行結果>

data1 = 8C
続行するには何かキーを押してください・・・

2進数で書くと↓の通りです。

  0xAF → 1010 1111

  0xCC → 1100 1100

    1010 1111
  & 1100 1100
  -----------
    1000 1100

  1000 1100 → 0x8C

次回は、使い道を考えながら色々やってみましょう。


次へ

戻る

目次へ