힘들면 쉬었다 가자.

무한루프 본문

프로그래밍/C/C++

무한루프

오클라호마호 2011. 3. 1. 16:56


예전에 수업시간에 잠깐 언급되었던 부분인데..

교수님께서 깊이 들어가기 싫어서 그러셨던건지..

약간 좀 다르게 설명하신 부분이 있어서

한번 적어 봅니다.

-------------------------------------

 

int i=1;

 

while(i>0){
    i++;
}

 

위 소스는 무한 루프일까요??

 

결론부터 말하자면 "아니다" 입니다.

왜 그럴까요??

다음 소스를 돌려 봅시다.

 

----------------------------------------------------------
#include <stdio.h>

int main()
{
    int i=1;
 
    while(i>0){
        i++;
    }

 

    puts("이 문장이 출력되면 무한 루프가 아니겠죠??");
    printf("i -> %d\n", i);

    return 0;
}
----------------------------------------------------------

 

시간이 조금 걸리기는 했지만 분명히 while() 루프의 밑에있는 문장이 출력되었습니다.





한가지 이상한것은 변수 i의 값이 -2147483648 이라는 값이 되었다는 것입니다.

뭐 시스템에 따라서 다를 수도 있겠지만, 일반적으로 signed int의 구조는(signed char, signed short 모두 마찬가지 입니다. 일반적으로 변수 선언 할 때 int a; 이런식으로 하게 되면 signed int가 되는거고, unsigned 변수는 명시적으로 unsigned로 선언해줘야 합니다.)
제일 상위 bit가 부호 비트가 됩니다. 컴퓨터 구조를 제대로 들었으면 금방 아셨을텐데 컴퓨터에서 음수를 처리하는 방식은 최상위 bit를 보고 이 숫자가 음수인지 양수인지를 판단하게 됩니다.


만약 해당 bit가 1이라면 음수, 0이면 양수가 되는 것이지요, 음수의 계산은 2의 보수를 이용해서 구하게 됩니다.
32bit는 너무 크니 4bit라고 가정을 하자면, 1101 이라는 수는 최상위 bit가 1이므로, 음수가 될 것이고 2의 보수를 구하면0010+1이니깐, 0011이 됩니다. 따라서 해당 숫자를 10진수로 표현하면 -3이 됩니다.

 

그럼 i는 1이었는데 어떻게 저런 쌩뚱맞은 숫자가 되었을까요??

 

while() 루프안에서 i의 값을 1씩 계속 증가 시키고 있습니다. i는 32bit이고 이진수로 표현하자면,

00000000 00000000 00000000 00000001 이 될 것입니다. 루프를 한단계 거치면

00000000 00000000 00000000 00000010 이 되고 그 다음번에는

00000000 00000000 00000000 00000011 .. 이런식으로 계속 가다보면 언젠가는

01111111 11111111 11111111 11111111 이 될 것입니다.

 

그리고 (지금부터가 중요합니다.) 이 다음번 루프를 돌면 값은 10000000 00000000 00000000 00000000 이 됩니다. 그럼 이 값은 최상위 bit가 1이기 때문에 더이상 양수가 아닙니다. 양수였던 값이 i++을 한번 더 했을 뿐인데 음수가 된 것이죠. 10진수로 표현하면 2의 보수가 01111111 11111111 11111111 11111111+1이고 이 값은 -(10000000 00000000 00000000 00000000) 이니깐 바로 -2147483648 이라는 값이 되는 것입니다. (해당 자릿수가 31번째 자리이므로 2의 31승이 됩니다.)

 

아직 무슨 소린지 잘 모를수도 있는데, 컴퓨터가 부호있는 정수를 어떻게 처리하는지 알게 되면 '이런 당연한 소리를 왜 하나' 하고 생각하시게 될 것입니다.

 

참고로 -2147483648는 signed integer가 가질 수 있는 가장 작음 음수 값입니다. 그럼 signed integer가 가질 수 있는 가장 큰 양수 값은 무엇일까요?? 2147483648일까요??

 

답은 2147483647입니다. 이건 2의 보수랑 sign bit를 잘 생각해 보면 왜 1이 작은 지 알수 있습니다. C에서는 오버플로 체크가 안되기 때문에 저 숫자를 알고 있어야 할 때가 가끔 있는데, 해당 값은 <limit.h> 파일안에 정의가 되어있습니다.

 

#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
#define INT_MAX       2147483647       /* maximum (signed) int value */

 

 

 

Comments