signed/unsigned 정수 연산 때문에 생긴 오류 .
다음 코드를 보자.
여기서 중요한 것은
signed 64비트 정수에서 unsigned 64비트를 빼는 것이다.
size 는 MAX_SIZE 보다 1이 작다. 결과는 물론 -1 이 나와야 한다.
출력 결과는 어떻게 될까 ?
희한하게도 다음과 같다.
이 문제 때문에 엄청난 시간을 낭비했다.
디버깅 끝에 위와 같은 문제를 발견했는데, if문 안에서의 결과가 우리가 예상하는 바와는 반대이다.
결국 MAX_SIZE 를 signed 정수로 선언하여 문제를 해결 하긴 했지만,
뭔가 찜찜한 마음을 지울 수는 없다.
혹시 이유를 아시는 분은 답변 좀 알려주세요.
(아 컴파일러는 gcc (GCC) 4.0.4 20060507)
+ 32비트 정수로 다시 테스트 해 보니 역시 같은 결과가 나온다.
결국은 if 문 안에서 계산할 때는 타입에 신경써야 한다는 결론은 얻었다 -_-;;
다음 코드를 보자.
typedef signed long long int64;
typedef unsigned long long uint64;
int main(int argc, char *argv[])
{
const uint64 MAX_SIZE = uint64(2)*1024*1024*1024;
int64 size = int64(2)*1024*1024*1024-1;
int64 result = size - MAX_SIZE;
printf("%lld\n", result);
if( size - MAX_SIZE >= 0 ){
printf("NO\n");
}
else{
printf("OK\n");
}
return 0;
}
typedef unsigned long long uint64;
int main(int argc, char *argv[])
{
const uint64 MAX_SIZE = uint64(2)*1024*1024*1024;
int64 size = int64(2)*1024*1024*1024-1;
int64 result = size - MAX_SIZE;
printf("%lld\n", result);
if( size - MAX_SIZE >= 0 ){
printf("NO\n");
}
else{
printf("OK\n");
}
return 0;
}
여기서 중요한 것은
signed 64비트 정수에서 unsigned 64비트를 빼는 것이다.
size 는 MAX_SIZE 보다 1이 작다. 결과는 물론 -1 이 나와야 한다.
출력 결과는 어떻게 될까 ?
희한하게도 다음과 같다.
-1
NO
NO
이 문제 때문에 엄청난 시간을 낭비했다.
디버깅 끝에 위와 같은 문제를 발견했는데, if문 안에서의 결과가 우리가 예상하는 바와는 반대이다.
결국 MAX_SIZE 를 signed 정수로 선언하여 문제를 해결 하긴 했지만,
뭔가 찜찜한 마음을 지울 수는 없다.
혹시 이유를 아시는 분은 답변 좀 알려주세요.
(아 컴파일러는 gcc (GCC) 4.0.4 20060507)
+ 32비트 정수로 다시 테스트 해 보니 역시 같은 결과가 나온다.
결국은 if 문 안에서 계산할 때는 타입에 신경써야 한다는 결론은 얻었다 -_-;;
댓글을 달아 주세요
우선 표준에서 연산할 때 부호있는 숫자와 부호없는 숫자를 연산하면 부호없는 숫자가 된다.
그런데 printf에서는 %d를 썼기 때문에(부호있는 출력, 부호없는 출력은 %u) -1로 출력했지만,
if문에서는 저 연산 결과가 부호 없는 수이기 때문에 무조건 참이 된다.
고로 연산할 때는 부호에 각별히 신경쓰는 것이 좋다. (오버플로의 문제도 있을 수 있으므로..)
저 코드에서는..
int64 result = size - MAX_SIZE;
if ( result >= 0 )
...
으로 검사했다면 정상적으로 작동했을 것이다.
그렇지요 그래서 코드 만들 때 타입을 잘 결정하는 것도 중요하고,
명시적인 캐스팅도 중요하고 ...
-_-; warning 없는 코드 만들기 중요하죠 : )