GCC(GNU Compiler Collection) 컴파일러는 개발자의 편의를 위해 다양한 내장 함수(built-in functions)를 제공합니다. 이 함수들은 별도의 라이브러리 포함 없이 바로 사용할 수 있으며, 특히 비트 연산 관련 작업에서 성능과 코드 간결성 면에서 큰 장점을 가집니다. 이번 글에서는 자주 사용되는 대표적인 내장 함수 네 가지를 예제와 함께 살펴보겠습니다.
1. __builtin_popcount(x) – 1비트 개수 세기
__builtin_popcount()는 정수를 이진수로 표현했을 때 1의 개수를 반환하는 함수입니다. 비트마스킹 문제나 해밍 거리 계산 등에 유용하게 활용됩니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int n = 13; // 13의 이진수 표현은 1101
cout << "13의 이진수에서 1의 개수는 " << __builtin_popcount(n);
return 0;
}실행 결과
13의 이진수에서 1의 개수는 3
2. __builtin_parity(x) – 패리티 검사
__builtin_parity()는 숫자의 패리티(parity)를 확인하는 함수입니다. 이진수 표현에서 1의 개수가 홀수이면 참(1)을, 짝수이면 거짓(0)을 반환합니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int n = 13; // 13의 이진수 표현은 1101
cout << "13의 패리티 값은 " << __builtin_parity(n);
return 0;
}실행 결과
13의 패리티 값은 1
13(1101)은 1이 세 개, 즉 홀수 개이므로 결과로 1이 출력됩니다.
3. __builtin_clz(x) – 선행 0의 개수 세기
__builtin_clz()는 정수의 이진수 표현에서 최상위 비트 앞에 있는 0의 개수(Count Leading Zeros)를 반환합니다. 32비트 int 기준으로 동작하며, 최상위 유효 비트(MSB)의 위치를 구할 때 자주 사용됩니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int n = 13; // 13의 이진수 표현은 1101
// 0000 0000 0000 0000 0000 0000 0000 1101 (32비트 정수)
cout << "13의 선행 0 개수는 " << __builtin_clz(n);
return 0;
}실행 결과
13의 선행 0 개수는 28
32비트 중 실제 데이터가 있는 비트는 뒤의 4자리뿐이므로, 앞쪽의 0은 32 − 4 = 28개가 됩니다.
4. __builtin_ctz(x) – 후행 0의 개수 세기
__builtin_ctz()는 정수의 이진수 표현에서 최하위 비트 뒤에 있는 0의 개수(Count Trailing Zeros)를 반환합니다. 어떤 수가 2의 몇 제곱으로 나누어지는지 확인할 때 유용합니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int n = 12; // 12의 이진수 표현은 1100
// 0000 0000 0000 0000 0000 0000 0000 1100 (32비트 정수)
cout << "12의 후행 0 개수는 " << __builtin_ctz(n);
return 0;
}실행 결과
12의 후행 0 개수는 2
마무리
GCC의 내장 함수들은 반복문을 직접 작성하지 않고도 비트 연산 관련 기능을 빠르고 간결하게 처리할 수 있게 해줍니다. 단, 이러한 함수는 GCC 전용 확장 기능이므로 이식성(portability)이 중요한 프로젝트에서는 주의해야 합니다. 알고리즘 문제 풀이나 성능 최적화가 필요한 상황이라면 위 함수들을 적극적으로 활용해 보시기 바랍니다.