'64비트 정수 계산'에 해당되는 글 1건

  1. 2007/12/06 이상한 정수 계산 (3)
signed/unsigned 정수 연산 때문에 생긴 오류 .

다음 코드를 보자.

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;
}

여기서 중요한 것은
signed 64비트 정수에서 unsigned 64비트를 빼는 것이다.
size 는 MAX_SIZE 보다 1이 작다. 결과는 물론 -1 이 나와야 한다.

출력 결과는 어떻게 될까 ?
희한하게도 다음과 같다.

-1
NO

이 문제 때문에 엄청난 시간을 낭비했다.
디버깅 끝에 위와 같은 문제를 발견했는데, if문 안에서의 결과가 우리가 예상하는 바와는 반대이다.
결국 MAX_SIZE 를 signed 정수로 선언하여 문제를 해결 하긴 했지만,
뭔가 찜찜한 마음을 지울 수는 없다.

혹시 이유를 아시는 분은 답변 좀 알려주세요.

(아 컴파일러는 gcc (GCC) 4.0.4 20060507)


+ 32비트 정수로 다시 테스트 해 보니 역시 같은 결과가 나온다.
결국은 if 문 안에서 계산할 때는 타입에 신경써야 한다는 결론은 얻었다 -_-;;

Trackback Address :: http://seirion.com/trackback/56 관련글 쓰기

댓글을 달아 주세요

  1. |꼬마늑대| 2008/01/10 04:26 Address Modify/Delete Reply

    우선 표준에서 연산할 때 부호있는 숫자와 부호없는 숫자를 연산하면 부호없는 숫자가 된다.
    그런데 printf에서는 %d를 썼기 때문에(부호있는 출력, 부호없는 출력은 %u) -1로 출력했지만,
    if문에서는 저 연산 결과가 부호 없는 수이기 때문에 무조건 참이 된다.
    고로 연산할 때는 부호에 각별히 신경쓰는 것이 좋다. (오버플로의 문제도 있을 수 있으므로..)

    • |꼬마늑대| 2008/01/10 04:28 Address Modify/Delete

      저 코드에서는..
      int64 result = size - MAX_SIZE;
      if ( result >= 0 )
      ...
      으로 검사했다면 정상적으로 작동했을 것이다.

    • 바보세룐 2008/01/10 09:07 Address Modify/Delete

      그렇지요 그래서 코드 만들 때 타입을 잘 결정하는 것도 중요하고,
      명시적인 캐스팅도 중요하고 ...
      -_-; warning 없는 코드 만들기 중요하죠 : )