비트 연산과 관련하여 gcc 내부에 정의된 빌트인 함수들이 있다. 이를 사용하면 사용자가 직접 알고리즘을 구현해야 할 수고를 덜 수 있으며, 크면 단일 명령어 수준으로까지 코드가 줄어들기 때문에 코드 크기도 줄고 속도도 더 빨라진다.
x의 값을 이진수로 나타냈을 때, 1의 개수를 세는 빌트인 함수이다.
예)
#include <stdio.h>
int main()
{
int a = 5, b = 7;
printf("%d\n", __builtin_popcount(a)); // 0b0101 : two
printf("%d\n", __builtin_popcount(b)); // 0b0111 : three
return 0;
}
출력 결과
> 2
3
5와 7을 이진수로 나타내면 0101, 0111이며, 1이 각각 두 개, 세 개 들어있기 때문에 2와 3이 각각 출력된다.
(함수 이름이 왜 popcount지?)
x의 패리티 비트를 구하는 빌트인 함수이다. x의 값을 이진수로 나타냈을 때, 1의 개수가 홀수이면 1, 짝수이면 0을 반환한다.
예)
#include <stdio.h>
int main()
{
int a = 5, b = 7;
printf("%d\n", __builtin_parity(a)); // 0b0101 : two
printf("%d\n", __builtin_parity(b)); // 0b0111 : three
return 0;
}
출력 결과
> 0
1
5와 7을 이진수로 나타내면 0101, 0111이며, 1이 각각 두 개, 세 개 들어있기 때문에 0과 1이 각각 출력된다.
clz는 count leading zeros의 줄임말로, 이어지는 0의 개수를 세는 빌트인 함수이다. x의 값을 이진수로 나타냈을 때, MSB부터 오른쪽으로 이동하여 1이 나오기 직전까지의 0의 개수를 반환한다. (MSB 포함)
예)
#include <stdio.h>
int main()
{
int a = 5, b = 9; // 32bit signed integer type
printf("%d\n", __builtin_clz(a)); // 00000000 00000000 00000000 00000101 : 29
printf("%d\n", __builtin_clz(b)); // 00000000 00000000 00000000 00001001 : 28
return 0;
}
출력 결과
> 29
28
MSB를 포함하여 왼쪽에서 오른쪽으로 셌을 때 1이 나오기 직전까지의 0의 개수가 5는 29개, 9는 28개인 것을 볼 수 있다.
ctz는 count trailing zeros의 줄임말로, clz와 유사하나 LSB부터 왼쪽으로 이동하여 1이 나오기 직전까지의 0의 개수를 반환한다. (LSB 포함)
예)
#include <stdio.h>
int main()
{
int a = 16, b = 32; // 32bit signed integer type
printf("%d\n", __builtin_ctz(a)); // 00000000 00000000 00000000 00010000 : 4
printf("%d\n", __builtin_ctz(b)); // 00000000 00000000 00000000 00100000 : 5
return 0;
}
출력 결과
> 4
5
LSB를 포함하여 오른쪽에서 왼쪽으로 셌을 때 1이 나오기 직전까지의 0의 개수가 16은 4개, 32는 5개인 것을 볼 수 있다.
더 다양한 예제가 필요해보임.