C 언어에서의 비트 연산자

안녕하세요, 미래의 코딩 마법사 여러분! 오늘은 C 언어에서의 비트 연산자의 세계로 흥미진진한 여정을 떠날 거예요. 프로그래밍에 새로운 사람이라도 걱정 마세요; 저는 여러분의 친절한 가이드로서 단계별로 모든 것을 설명해 드릴 거예요. 그럼, 학습의 모자를 쓰고, 함께 빠져나가 볼까요!

C - Bitwise Operators

비트 연산자란 무엇인가요?

시작하기 전에, 비트 연산자가 무엇인지 이해해 보죠. 전등 스위치가 한 무더기 있는 것을 상상해 보세요. 비트 연산자는 이러한 스위치를 흥미로운 방식으로 제어할 수 있는 특별한 도구처럼 동작합니다 - 켜고 끄거나, 심지어 상태를 교환할 수도 있습니다. 컴퓨터 세계에서는 이러한 "스위치"가 실제로 우리의 데이터를 구성하는 비트(0과 1)입니다.

이제, 하나씩 비트 연산자를 탐구해 보겠습니다.

C 언어에서의 비트 AND 연산자 (&)

비트 AND 연산자는 두 입력이 모두 동의할 때만 "예"를 말하는 친구처럼 동작합니다. 두 숫자의 각 비트를 비교하고, 두 비트가 모두 1이라면 1을 반환합니다. 그렇지 않으면 0을 반환합니다.

예를 들어보죠:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 in binary
unsigned int b = 13;  // 13 = 0000 1101 in binary

printf("a & b = %d\n", a & b);

return 0;
}

출력:

a & b = 12

이게 무슨 일이 일어나고 있는 거죠? 자, 분석해 보죠:

0011 1100  (60 in binary)
& 0000 1101  (13 in binary)
----------
0000 1100  (12 in decimal)

두 숫자가 모두 1이 아니면 1을 유지하지 않는 이 상황을 보세요? 그게 비트 AND의 마법입니다!

C 언어에서의 비트 OR (|) 연산자

비트 OR 연산자는 두 입력 중 하나라도 동의하면 "예"를 말하는 munificent한 친구처럼 동작합니다. 해당 비트 중 적어도 하나가 1이라면 1을 반환합니다.

예를 들어보죠:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 in binary
unsigned int b = 13;  // 13 = 0000 1101 in binary

printf("a | b = %d\n", a | b);

return 0;
}

출력:

a | b = 61

자, 분석해 보죠:

0011 1100  (60 in binary)
| 0000 1101  (13 in binary)
----------
0011 1101  (61 in decimal)

두 숫자 중 하나라도 1이 있는 곳을 모두 1로 유지하는 것을 보세요? 그게 비트 OR입니다!

C 언어에서의 비트 XOR (^) 연산자

XOR 연산자는 서로 다른 것을 좋아하는 이상한 친구처럼 동작합니다. 비트가 다르면 1을 반환하고, 같으면 0을 반환합니다.

그것을 보여드리죠:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 in binary
unsigned int b = 13;  // 13 = 0000 1101 in binary

printf("a ^ b = %d\n", a ^ b);

return 0;
}

출력:

a ^ b = 49

이게 무슨 일이 일어나고 있는 거죠?

0011 1100  (60 in binary)
^ 0000 1101  (13 in binary)
----------
0011 0001  (49 in decimal)

XOR는 암호화에 자주 사용됩니다. 왜냐하면 쉽게 되돌릴 수 있기 때문입니다. 숫자를 두 번 동일한 값으로 XOR하면 원래의 숫자를 돌려받을 수 있습니다. 멋질 히트?

C 언어에서의 왼쪽 시프트 (<<) 연산자

왼쪽 시프트 연산자는 비트를 왼쪽으로 이동하는 컨베이어 벨트처럼 동작합니다. 각 비트를 지정된 수만큼 왼쪽으로 이동합니다.

이렇게 동작합니다:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 in binary

printf("a << 2 = %d\n", a << 2);

return 0;
}

출력:

a << 2 = 240

자, 분석해 보죠:

0011 1100  (60 in binary)
<<2 (shift left by 2)
----------
1111 0000  (240 in decimal)

비트가 왼쪽으로 이동하고, 오른쪽에서 새로운 0이 채워지는 것을 보셨나요? 또한, 왼쪽으로 1만큼 시프트는 2로 곱하는 것과 같습니다. 그래서 왼쪽으로 2만큼 시프트는 4로 곱하는 것과 같습니다!

C 언어에서의 오른쪽 시프트 (>>) 연산자

오른쪽 시프트 연산자는 왼쪽 시프트의 반대 트윈처럼 동작합니다. 비트를 오른쪽으로 이동합니다.

예를 들어보죠:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 in binary

printf("a >> 2 = %d\n", a >> 2);

return 0;
}

출력:

a >> 2 = 15

이게 무슨 일이 일어나고 있는 거죠?

0011 1100  (60 in binary)
>>2 (shift right by 2)
----------
0000 1111  (15 in decimal)

비트가 오른쪽으로 이동하고, 왼쪽에서 새로운 0이 채워집니다. 오른쪽으로 1만큼 시프트는 2로 나누는 것과 같습니다 (나머지는 무시됩니다).

C 언어에서의 1's 보수 (~) 연산자

1's 보수 연산자는 비트의 미러처럼 동작합니다. 모든 비트를 0에서 1로, 1에서 0으로 뒤집습니다.

이렇게 동작합니다:

#include <stdio.h>

int main() {
unsigned int a = 60;  // 60 = 0011 1100 in binary

printf("~a = %u\n", ~a);

return 0;
}

출력:

~a = 4294967235

이게 무슨 일이 일어나고 있는 거죠? 자, 분석해 보죠:

0000 0000 0000 0000 0000 0000 0011 1100  (60 in 32-bit binary)
~(1's complement)
----------------------------------------
1111 1111 1111 1111 1111 1111 1100 0011  (4294967235 in decimal)

모든 0이 1이 되고, 모든 1이 0이 됩니다. 결과가 크게 보이는 이유는 unsigned int를 사용하고 있기 때문입니다. 모든 1을 긍정수로 해석하기 때문입니다.

결론

그리고 여러분! 우리는 C 언어에서의 비트 연산자의 세계를 여행했습니다. 이러한 강력한 도구는 처음에는 약간 까다롭을 수 있지만, 연습을 통해 매우 유용하게 사용할 수 있습니다. 하드웨어와 작업하거나, 코드 최적화 또는 심지어 binary 수학을 포함한 멋진 파티 트릭(파티가 binary 수학을 포함하면)에 사용할 수 있습니다.

이 연산자를 마스터하기 위한 열쇠는 연습입니다. 이 연산자를 사용하여 자신만의 프로그램을 작성해 보세요. 다양한 숫자를 실험해 보고, 어떤 결과를 얻을 수 있는지 확인해 보세요. 알고보면, 이들이 최고의 비트 트윔러이가 될 것입니다!

코딩을 즐기세요, 그리고 여러분의 성공을 기원합니다!

연산자 기호 설명
AND & 두 비트가 모두 1이면 1을 반환하고, 그렇지 않으면 0을 반환
OR | 적어도 하나의 비트가 1이면 1을 반환하고, 그렇지 않으면 0을 반환
XOR ^ 비트가 다르면 1을 반환하고, 같으면 0을 반환
왼쪽 시프트 << 비트를 지정된 수만큼 왼쪽으로 이동
오른쪽 시프트 >> 비트를 지정된 수만큼 오른쪽으로 이동
1's 보수 ~ 모든 비트를 뒤집음 (0은 1이 되고, 1은 0이 됨)

Credits: Image by storyset