C/C++에서 비트 AND(bitwise AND)는 &로 표현되고, 논리 AND(logical AND)는 &&로 표현됩니다. 두 연산자는 이름이 비슷하지만 동작 방식과 용도가 완전히 다르기 때문에, 이 차이를 정확히 이해하는 것은 버그를 예방하고 올바른 코드를 작성하는 데 매우 중요합니다.
1. 연산 대상과 반환 값의 차이
- 논리 AND(
&&)는 불리언(Boolean) 표현식에만 사용되며, 결과 역시 참(true) 또는 거짓(false)인 불리언 값으로 반환됩니다. - 비트 AND(
&)는 int, short int, long, unsigned int 등 정수 계열 데이터에 사용되며, 연산 결과도 해당 데이터 타입 그대로 반환됩니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int x = 3; // ...0011
int y = 7; // ...0111
if (y > 1 && y > x)
cout << "y is greater than 1 AND x" << endl;
int z = x & y; // 0011
cout << "z = "<< z;
}실행 결과
y is greater than 1 AND x z = 3
위 예제에서 y > 1 && y > x는 두 조건식의 참/거짓을 판단하는 논리 연산입니다. 반면 x & y는 각 비트끼리 AND 연산을 수행하여 0011 & 0111 = 0011, 즉 3이라는 정수 결과를 얻습니다.
2. 단락 평가(Short-Circuit Evaluation) 여부
&&연산자는 첫 번째 피연산자가 거짓(false)이면 두 번째 피연산자를 아예 평가하지 않습니다. 마찬가지로||연산자도 첫 번째 피연산자가 참(true)이면 두 번째 피연산자를 건너뜁니다. 이를 단락 평가(short-circuit evaluation)라고 합니다.- 반면
&,|같은 비트 연산자는 조건과 관계없이 항상 양쪽 피연산자를 모두 평가합니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int x = 0;
cout << (x && printf("Test using && ")) << endl;
cout << (x & printf("Test using & "));
}실행 결과
0 Test using & 0
위 코드에서 x는 0(거짓)이므로 &&를 사용한 첫 번째 문장은 오른쪽의 printf를 실행하지 않고 바로 0을 출력합니다. 하지만 &를 사용한 두 번째 문장은 피연산자를 모두 평가해야 하므로 printf("Test using & ")가 실제로 실행되어 문자열이 화면에 출력된 후 결과가 계산됩니다.
정리
| 구분 | 논리 AND (&&) | 비트 AND (&) |
|---|---|---|
| 연산 대상 | 불리언 표현식 | 정수 계열 데이터 |
| 반환 값 | true / false | 비트 연산 결과(정수) |
| 단락 평가 | 지원함 | 지원하지 않음(항상 양쪽 평가) |
조건 판단에는 &&를, 비트 단위의 플래그 처리나 마스킹(masking) 작업에는 &를 사용하는 것이 올바른 C/C++ 프로그래밍 습관입니다.