본문 바로가기
카테고리 없음

C언어 - 비트 연산자 총정리

by kik328288 2026. 5. 5.

비트 연산 (AND, OR, XOR, 시프트)

C언어가 시스템 프로그래밍의 표준 언어로 오랜 시간 자리를 지켜온 핵심 이유 중 하나는 메모리의 비트(Bit) 수준까지 직접 다룰 수 있다는 점이다. 운영체제 커널, 임베디드 펌웨어, 네트워크 프로토콜 구현 같은 영역에서는 한 바이트의 어떤 비트가 1인지 0인지를 정확히 제어하는 능력이 곧 성능과 효율을 결정한다. 이를 가능하게 하는 도구가 비트 연산자(Bitwise Operator)이며, AND·OR·XOR·NOT의 네 가지 논리 연산자와 좌·우 시프트의 두 가지 이동 연산자로 구성된다(출처: cppreference — Bitwise operators). 정보처리기사 실기에서도 비트 연산의 결과를 2진수와 10진수로 추적하는 문제가 자주 출제된다. 본 글은 여섯 가지 비트 연산자의 의미와 활용 패턴, 그리고 시험 빈출 예제를 코드와 함께 정리한다. 제가 학교 임베디드 동아리에서 처음 8비트 센서 값을 비트 마스킹으로 분리해 봤을 때 같은 1바이트가 두 개의 4비트 정보로 깔끔하게 분리되는 모습을 본 후로는 비트 연산이 단순한 시험 항목이 아니라 시스템 프로그래밍의 기초 체력이라는 점을 손끝으로 받아들였다.

비트 논리 연산자 — AND, OR, XOR, NOT

비트 논리 연산자는 두 정수의 같은 위치 비트끼리 논리 연산을 수행한다. 일반적인 논리 연산자(&&, ||, !)가 식 전체를 참 또는 거짓으로 평가하는 반면, 비트 연산자는 각 자리 비트마다 독립적으로 동작한다는 점이 결정적인 차이이다.

연산자 동작 한 비트 결과 대표 용도
& (AND) 둘 다 1 1 비트 마스킹·추출
| (OR) 하나라도 1 1 특정 비트 설정
^ (XOR) 서로 다르면 1 1 토글·값 교환
~ (NOT) 단항 반전 마스크 생성
int a = 12;   // 0000 1100
int b = 10;   // 0000 1010

printf("%d\n", a & b);   // 0000 1000 = 8
printf("%d\n", a | b);   // 0000 1110 = 14
printf("%d\n", a ^ b);   // 0000 0110 = 6
printf("%d\n", ~a);      // 1111 0011 = -13 (2의 보수)

비트 NOT 연산자의 결과가 음수로 나오는 이유는 C언어의 정수가 2의 보수(two's complement) 형식으로 표현되기 때문이다. 여기서 2의 보수란 양수의 모든 비트를 반전시킨 뒤 1을 더해 음수를 표현하는 정수 인코딩 방식을 가리키며, 부호 연산을 별도 회로 없이 같은 가산기로 처리할 수 있게 해 주어 거의 모든 현대 CPU가 채택하고 있다. 12의 모든 비트를 뒤집으면 부호 비트까지 1이 되어 음수로 해석된다.

비트 연산은 짝수와 홀수 판별, 플래그 검사, 권한 비트 처리 같은 실무 작업에 광범위하게 활용된다. 예를 들어 한 정수의 가장 낮은 비트를 검사하면 그 수가 짝수인지 홀수인지를 단 한 번의 AND 연산으로 알 수 있다.

int n = 7;
if (n & 1) printf("홀수\n");   // 마지막 비트 = 1 → 홀수
else       printf("짝수\n");

시프트 연산과 비트 마스킹 응용

시프트 연산자는 비트들을 좌우로 이동시키는 연산이며, 두 가지 방향이 있다. 좌측 시프트(<<)는 비트들을 왼쪽으로 옮기고 오른쪽 빈자리는 0으로 채운다. 결과적으로 정수를 2의 거듭제곱만큼 곱한 값과 같다. 우측 시프트(>>)는 비트들을 오른쪽으로 옮기며, 부호 있는 정수에서는 부호 비트를 그대로 채우는 산술 시프트(arithmetic shift)가 적용되어 음수의 부호가 유지된다. 여기서 산술 시프트란 부호 비트를 유지하면서 오른쪽으로 이동시키는 시프트 방식으로, 정수 나눗셈과 동일한 결과를 만든다.

int x = 5;             // 0000 0101
printf("%d\n", x << 2); // 0001 0100 = 20  (5 * 4)
printf("%d\n", x << 3); // 0010 1000 = 40  (5 * 8)

int y = 40;             // 0010 1000
printf("%d\n", y >> 2); // 0000 1010 = 10  (40 / 4)
printf("%d\n", y >> 3); // 0000 0101 = 5   (40 / 8)

이러한 비트 연산자들을 결합하면 비트 마스킹(Bit Masking)이라는 강력한 기법을 만들 수 있다. 마스크는 특정 위치의 비트만 1로 설정해 놓은 정수이며, AND·OR·XOR과 결합해 원하는 비트만 추출하거나, 설정하거나, 토글할 수 있다.

unsigned char flags = 0;

// 1) 특정 비트 설정 (3번 비트를 1로)
flags |= (1 << 3);    // 0000 1000 = 8

// 2) 특정 비트 해제 (3번 비트를 0으로)
flags &= ~(1 << 3);   // 0000 0000 = 0

// 3) 특정 비트 토글 (5번 비트 반전)
flags ^= (1 << 5);    // 0010 0000 = 32

// 4) 특정 비트 검사
if (flags & (1 << 5)) printf("bit 5 ON\n");

이 네 패턴은 권한 관리, 파일 모드 비트, 그래픽스의 색상 채널 추출 등 다양한 실무 영역에서 표준적으로 사용된다. 예를 들어 리눅스 파일 권한의 읽기·쓰기·실행 비트를 다루거나, RGB 색상의 빨간 채널을 분리하거나, 하드웨어 제어 레지스터의 특정 비트만 조작하는 모든 작업이 동일한 원리로 동작한다. 솔직히 이건 예상 밖이었는데, 학교에서 시험 항목으로만 외웠던 비트 마스킹이 실제 임베디드 코드의 거의 한 줄 걸러 등장하는 모습을 본 후로는 "비트 연산은 학습 항목이 아니라 영구적인 도구"라는 점을 받아들였다.

정보처리기사 실기 빈출 비트 연산 예제

정보처리기사 실기에서 비트 연산은 단순 출력 문제로 가장 많이 등장한다(출처: Q-Net 정보처리기사).

유형 1 — 기본 비트 연산 결과 추적.

int a = 13;   // 0000 1101
int b = 9;    // 0000 1001
printf("%d\n", a & b);  // 0000 1001 = 9
printf("%d\n", a | b);  // 0000 1101 = 13
printf("%d\n", a ^ b);  // 0000 0100 = 4

가장 기본적인 패턴이지만 출제 빈도가 가장 높다. 두 수를 2진수로 변환한 뒤 자릿수별로 연산하는 절차를 빠르게 수행할 수 있어야 한다.

유형 2 — 시프트 연산과 곱셈·나눗셈의 등가성.

int x = 6;
printf("%d\n", x << 2);  // 6 * 4 = 24
printf("%d\n", x >> 1);  // 6 / 2 = 3

int y = 17;
printf("%d\n", y >> 2);  // 17 / 4 = 4 (소수점 버림)

좌측 시프트는 곱셈, 우측 시프트는 나눗셈과 같다는 등가성을 묻는다. 우측 시프트 결과에서 소수점 이하가 버려진다는 점이 자주 출제된다.

유형 3 — XOR을 활용한 값 교환.

int a = 5, b = 3;
a = a ^ b;   // a = 0110
b = a ^ b;   // b = 0101 = 5
a = a ^ b;   // a = 0011 = 3
printf("%d %d\n", a, b);  // 3 5

임시 변수 없이 두 변수를 교환하는 XOR 트릭이다. 자주 쓰는 코드는 아니지만 시험에서는 단골 손님이며, XOR이 같은 값으로 두 번 적용되면 원래 값이 된다는 성질이 핵심 원리이다. 본 글로 #26 변수와 데이터 타입에서 시작한 C언어 10편 시리즈가 마무리된다. 변수·제어문·함수·포인터·배열·구조체·동적 메모리·파일 입출력·전처리기·비트 연산이라는 열 가지 토대를 갖춘 독자라면, 이제 자료구조와 운영체제로 학습 영역을 확장할 준비가 충분히 갖추어졌다고 할 수 있다. 솔직히 제 경험상 이 열 편을 모두 손으로 한 번씩 작성해 보고 나서야 "C언어는 단순한 언어가 아니라 시스템을 보는 시선"이라는 인상을 비로소 받아들였다.


메타 디스크립션: C언어 비트 연산자 & | ^ ~ << >>의 의미와 동작, 비트 마스킹을 활용한 플래그 설정·해제·토글·검사 패턴, 그리고 정보처리기사 실기 빈출 3패턴을 코드 예시와 함께 정리합니다. C언어 10편 시리즈 마무리 글입니다.


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 블로그 이름