トップC言語入門 > C言語における論理演算

C言語における論理演算

1.論理型(boolean)

Java には、データ型として、論理型 boolean がある。値は、true か false の2値しかとらない。

これに対して、C言語(C89)には論理型というデータ型はなく、int型が使われる(C99には論理型が定義されている)。 値 0 のとき偽(false)、0 以外のとき真(true) とみなされる。 例えば、次のプログラム

    if (a) printf("True!\n");
    else printf("False!\n");
は、次のプログラムと等価である。
    if (a != 0) printf("True!\n");
    else printf("False!\n");

2.論理和(Logical Or)

次のプログラムでは、a, b, c の値が全て 0 であれば False となり、 0 でないものが一つでもあれは True となる。

    if (a || b || c) printf("True\n");
    else printf("False\n");

もし a が非ゼロならば、"真" が決定するため、b, c は評価(実行)されない。 すなわち、上のプログラムは次のプログラムと等価である。

    if (a) printf("True\n");
    else if (b) printf("True\n");
    else if (c) printf("True\n");
    else printf("False\n");

このことは次のプログラムを実行することにより確認できる。

// or01.c
#include <stdio.h>

int OR(int a, int b, int c) {
    int z;
    printf("実行前: %d || %d || %d\n", a, b, c);
    z = a++ || b++ || c++;
    printf("実行後: %d || %d || %d = %d\n", a, b, c, z);
    return z;
}

int main() {
    OR(0, 2, 0);
    OR(0, -2, 0);
    OR(0, 0, 0);
}

このプログラムでは、a++, b++, c++ の評価が行われれば、値が +1 される。 最初の OR(0, 2, 0) では、a++, b++ を実行した段階で、"真" となるため、 c++ は実行されない。次の OR(0, -2, 0) でも同じである。 最後の OR(0, 0, 0) では、a++, b++, c++ の全ての評価が行われる。

c:\MH\www\c01\logicoperation>or01
実行前: 0 || 2 || 0
実行後: 1 || 3 || 0 = 1
実行前: 0 || -2 || 0
実行後: 1 || -1 || 0 = 1
実行前: 0 || 0 || 0
実行後: 1 || 1 || 1 = 0

3.論理積(Logical And)

次のプログラムでは、a, b, c の値が全て非ゼロであれば True となり、 0 が一つでもあれは False となる。

    if (a && b && c) printf("True\n");
    else printf("False\n");

もし a が 0 ならば、"False" が決定するため、b, c は評価(実行)されない。 すなわち、上のプログラムは次のプログラムと等価である。

    if (!a) printf("False\n");
    else if (!b) printf("False\n");
    else if (!c) printf("False\n");
    else printf("True\n");

このことは次のプログラムを実行することにより確認できる。

// and01.c
#include <stdio.h>

int AND(int a, int b, int c) {
    int z;
    printf("実行前: %d && %d && %d\n", a, b, c);
    z = a++ && b++ && c++;
    printf("実行後: %d && %d && %d = %d\n", a, b, c, z);
    return z;
}

int main() {
    AND(2, 2, 2);
    AND(1, -2, 0);
    AND(10, 0, 20);
}

このプログラムでは、a++, b++, c++ の評価が行われれば、値が +1 される。 AND(2, 2, 2), AND(1, -2, 0) では、a++, b++, c++ の全ての評価が行われる。 最後の OR(0, 0, 0) では、 a++, b++ を実行した段階で、"偽" となるため、c++ は実行されない。

c:\MH\www\c01\logicoperation>and01
実行前: 2 && 2 && 2
実行後: 3 && 3 && 3 = 1
実行前: 1 && -2 && 0
実行後: 2 && -1 && 1 = 0
実行前: 10 && 0 && 20
実行後: 11 && 1 && 20 = 0

4.プログラム例

論理積の使用例 test01.c を下に示す。for文の二つの終了条件を論理積で表現している。 このプログラムは n < NUM が成立しないときは、s[n] の評価は行われないことを利用している。 もし、このことが成り立たないならば、プログラムは test02.c のように書き換えなければならない。

// test01.c
#include <stdio.h>

#define NUM 10
char s[NUM] = "abc";

int main() {
  int n;
  for (n=0; n<NUM && s[n]!='\0'; n++) {
    printf("%d, ", s[n]);
  }
}
// test02.c
#include <stdio.h>

#define NUM 10
char s[NUM] = "abc";

int main() {
    int n;
    for (n = 0; n < NUM; n++) {
        if (s[n] == '\0') break;
        printf("%d, ", s[n]);
    }
}

5.コンパイラにとっての論理演算

例えばビットOR演算 int x = a | b | c; は

  x  = a;
  x |= b;
  x |= c;
のように簡単な命令文に書き下せる。 これに対して、 論理OR演算 int x = a || b || c; は、もっと複雑であり
  if (a != 0) goto locTrue;
  if (b != 0) goto locTrue;
  if (c != 0) goto locTrue;
  x = 0;
  goto locNext;
locTrue:
  x = 1;
locNext:
のように、分岐命令を含んだものとなる。 if 文
  if (a || b || c) stmtTrue
  else stmtFalse
の場合には、x = 0; のところが stmtFalse、 x = 1; のところが stmtTrue に置き換わり、次の形となる。
  if (a != 0) goto locTrue;
  if (b != 0) goto locTrue;
  if (c != 0) goto locTrue;
  stmtFalse
  goto locNext;
locTrue:
  stmtTrue
locNext: