22.1 비트 AND, OR, XOR 연산자 사용하기

이제 비트 연산자를 사용하여 값을 계산해보겠습니다. 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

  • a & b
  • a | b
  • a ^ b

bitwise_and_or_xor_operator.c

#include <stdio.h>
 
int main()
{
    unsigned char num1 = 1;    // 0000 0001
    unsigned char num2 = 3;    // 0000 0011
 
    printf("%d\n", num1 & num2);    // 0000 0001: 01과 11을 비트 AND하면 01이 됨
    printf("%d\n", num1 | num2);    // 0000 0011: 01과 11을 비트 OR하면 11이 됨
    printf("%d\n", num1 ^ num2);    // 0000 0010: 01과 11을 비트 XOR하면 10이 됨
 
    return 0;
}

실행 결과

1
3
2

각 줄에 해당 값의 10진수와 2진수(비트)를 적어놓았습니다. unsigned char 자료형에 1을 할당했을 때 비트로 표현하면 0000 0001입니다. 마찬가지로 30000 0011입니다.

앞으로 프로그래밍 분야에서 일하고자 한다면 10진수를 2진수(비트)로 표현하는 방법을 익히는 것이 좋습니다('33.9 배열을 활용하여 10진수를 2진수로 변환하기'참조).

아직 2진수로 표현하는 방법에 익숙하지 않을 때는 Windows의 계산기를 활용하면 편리합니다. 계산기를 실행하고 보기(V) > 프로그래머용(P)을 선택하면 다음과 같이 10진수를 2진수로 출력해줍니다.

그림 22‑1계산기로 10진수를 2진수로 출력

그림 23‑1에서는 10진수 3을 입력하였고 아래 부분에 2진수로 0011이 출력되었습니다. 각자 다른 숫자를 넣어서 2진수로 출력해보세요.

먼저 &, |, ^ 연산자로 각 비트를 연산했을 때의 결과(진리표)는 다음과 같습니다. 진리표의 내용이 많아 보여도 각 연산자의 특성만 이해하면 진리표 전체를 외우지 않아도 됩니다.

표 22‑2 &, |, ^ 연산 결과
연산자 비트1 비트2 결과
& 0 0 0
0 1 0
1 0 0
1 1 1
| 0 0 0
0 1 1
1 0 1
1 1 1
^ 0 0 0
0 1 1
1 0 1
1 1 0

비트 연산은 두 값을 비트 단위로 나열한 뒤 각 자릿수를 비트 연산자로 연산합니다. 각 자릿수의 연산은 독립적이며 다른 자릿수에 영향을 주지 않습니다. 그리고 비트 단위로 연산한 각 자릿수를 모두 모으면 최종 결과가 됩니다.

& 연산자는 비트 AND이므로 두 비트가 모두 1일 때 1입니다. 따라서 하나라도 0이면 0이 나옵니다. 즉, 0000 00010000 0011을 비트 AND 연산했을 때 0 & 10 그리고 1 & 11이 나오므로 0000 0001이 됩니다. 10진수로 표현하면 1 & 3은 1이 되겠죠?

그림 22‑2 비트 단위 연산

만약 120 & 26을 연산하면 어떻게 될까요?

0111 1000(120)
0001 1010(26)
_________ &
0001 1000(24)

0001 1000이 나오므로 10진수로 24가 됩니다.

| 연산자는 비트 OR이므로 두 비트 중 하나만 1이라도 1입니다. 따라서 두 비트가 모두 0일 때만 0입니다. 즉, 0000 00010000 0011을 비트 OR 연산했을 때 0 | 11 그리고 1 | 11이 나오므로 0000 0011이 됩니다. 10진수로 표현하면 1 | 33입니다.

0000 0001(1)
0000 0011(3)
_________ |
0000 0011(3)

^ 연산자는 비트 XOR이므로 두 비트가 다를 때 1입니다. 따라서 11일 때, 00일 때는 모두 0입니다. 즉, 0000 00010000 0011을 비트 XOR 연산했을 때 0 ^ 11 그리고 1 ^ 10이 나오므로 0000 0010이 됩니다. 10진수로 표현하면 1 ^ 32입니다.

0000 0001(1)
0000 0011(3)
_________ ^
0000 0010(2)