잡다한 지식/CS 베이스

#define 의 함정... 나만 빠짐

GGOBOOGI 2021. 3. 19. 17:25
반응형

음.. 뭔가 쓰려고 하니까 민망하긴 하지만 나색기 이런것도 까먹었음을 만천하에 공표하는 느낌으로다가 이제 안까먹어야지.

 

쓸데없이 오밤중에 새벽에 min heap을 구현하겠답시고 열심히 구현을 하다가 구현에서 이상한것도 아니고 쓸데없는것에서 이상한 것을 발견하였다.

 

무한대를 $2^{31}$ 로 정의하고 싶어서, 다음과 같이 define을 했었다.

#define INF 1<<31

그래. 당연히 $1<<31$은 $2^{31}$과 계산 결과가 같다.

 

그럼 여기서 문제.


INF - 1 의 값으로는 어떤 것이 나올까?

 

자 여기서 솔직히 이미 바닥나버린 양심이지만 바닥까지 긁어 모은 양심을 걸고 아 뭐야 당연히 $2^{31}-1$ 이지! 한 사람 나오세요.


저랑 동지입니다.^^

 

자 정답은 $2^{31 - 1} = 2^{30}$이다. ㄴㅇㄱ

상상도 못한 정체

 

define은 약간 의역(?) 코딩에서도 의역이 있었나  을 하자면 아 1<<31 맨날 쓰기 귀찮은데 INF라고 쓸게 걍! 이런 느낌이다.

 

따라서.. 만약

printf("%d", INF - 1);

이라고 썼을 경우, 이는

printf("%d", 1<<31 -1);

이 되는 것이다.

 

심지어 비트 연산자의 우선 순위보다 덧셈, 뺄셈의 우선 순위가 한 단계 더 높다. 따라서 뺄셈이 먼저 계산되기 때문에 쟤는 결국

printf("%d, 1<<30);

이 되는 것이다........

 

이거 모르고 이것저것 아래와 같이 출력해 보다가 INF_4 출력하고 깨달음을 얻음^^..

// #define INF 1<<31
printf("INF = %lld\nINF - 1 = %lld\n", INF, INF -1);

// #define INF_2 1<<30
printf("\nINF_2 = %lld\nINF_2 - 1 = %lld\n", INF_2, INF_2 -1);

// #define INF_3 2147483648
printf("\nINF_3 = %lld\nINF_3 - 1 = %lld\n", INF_3, INF_3 -1);

// #define INF_4 1<<3
printf("\nINF_4 = %lld\nINF_4 - 1 = %lld\n", INF_4, INF_4 -1);

/* 출력결과

INF = 2147483648
INF - 1 = 1073741824

INF_2 = 1073741824
INF_2 - 1 = 536870912

INF_3 = 2147483648    
INF_3 - 1 = 2147483647

INF_4 = 8
INF_4 - 1 = 4

*/

까먹지 말아야지... 눈물주룩

 

아니 근데 그럼 $2^{31}$을 애초에 define 할 때 부터 쓰고 싶으면 대체 어떻게 써야 잘 썼다고 할 수 있는 것인가?
2147483648를 외우고 다닐 수도 없고.. pow 함수같은것도 못 쓸 것이고..

 

지나가다 아시는 분 계시면 댓글 부탁드립니다...


오늘 랩실에서 이 문제를 @mttw2820에게 물어보았다.

 

결과적으로는 어제 대충 깃허브에서 찾아봤던 내용으로 해결이 되었다.

 

#define을 할 때, data type을 suffix로 명시하면 된다.

// signed int 1을 31만큼 left shift -> overflow
#define INF 1<<31

// unsigned int 1을 31만큼 left shift -> overflow 발생 안함
#define INF_2 1U<<31

어제 

오늘 새벽에

해보면서 위의 INF처럼 명시한 후, (INF)-1을 해보려고 했는데 편집기 linter가 뭐라고 뭐라고 잔소리하길래 귀찮아서 안읽고 잤는데, 맽튜가 듣고 해 보더니 그거 int범위 overflow 때문에 난 오류같다고 얘기를 해 줬다.

 

그래서 어제 열심히 이것저것 뒤져보다가 생각난 suffix data type을 명시해놓고 left shift를 했더니 잘 되더라.. 라는 후문.

 

위에서 정의한 INF_2는 overflow같은게 발생 안해서 (INF_2)-1 이렇게 써도 뭐 문제가 없이 생각했던 대로 잘 돌아간다.

 

suffix data type은 매우 여러 가지의 것들이 있다.


저 대신 정리한 사람이 많으니.. 링크를 걸어두겠어요..

 

그럼 이만 문제 해결 끝

반응형