728x90

int형이 아닌 정수형

정수를 처리해야 하는 일이 생겼을 때 int형만으로도 충분합니다. 하지만, C 언어에서는 int형이 아닌 다른 정수형들도 제공하고 있습니다.

C 언어는 기본 정수형을 변경할 수 있는 세 개의 형용사 키워드 short, long, unsigned를 제공합니다.

  • short int형(또는 short형)은 int형보다 더 적은 기억 공간을 사용할 수도 있습니다. 그래서 작은 수를 저장할 때 메모리를 절약할 수 있습니다. int형과 마찬가지로 short형도 부호가 있는(signed) 데이터형입니다.
  • long int형(또는 long형)은 int형보다 더 큰 기억 공간을 사용할 수도 있습니다. 그래서 더 큰 정수값들을 표현할 때 사용합니다. int형과 마찬가지로 long형도 부호가 있는 데이터형입니다.
  • long long int형(또는 long long형)은 long형보다 더 큰 기억 공간을 사용할 수도 있습니다. 이 자료형은 최소 64비트를 사용하며, C99 표준에서 추가되었습니다. int형과 마찬가지로 long long형도 부호가 있는 데이터형입니다.
  • unsinged int형(또는 unsigned형)은 음수가 아닌 값들을 저장할 때 사용됩니다. 이 데이터형은 저장할 수 있는 수의 범위가 변합니다. 예를 들어 16비트의 unsigned int형은 -32768에서 32767까지의 범위 대신 0에서 65535까지의 수를 저장할 수 있습니다. 부호를 나타냈던 비트를 값의 크기를 저장하는 2진수 숫자로 사용하면서, 더 큰 수를 표현할 수 있게 된 것입니다.
  • C90 표준에서 unsigned long int형(또는 unsigned long형), unsigned short int형(또는 unsigned short형)이 추가되었습니다.
    C99 표준에서 unsigned long long int형(또는 unsigned long long형)이 추가되었습니다.
  • 키워드 signed는 부호가 있는 데이터형에 그 의미를 더욱 명시적으로 나타내기 위해 사용합니다. 예를 들어 short, short int, signed short, signed short int는 전부 같은 데이터형의 이름입니다.


int형이 아닌 정수형을 선언하는 방법

다른 정수형의 변수들도 int형과 같은 방법으로 선언할 수 있습니다. 마지막 예시는 C99 표준에 새롭게 추가되어서 지원하지 않는 컴파일러가 있을 수 있습니다.

long int one;
long two;

short int one;
short two;

unsigned int one;
unsigned one;

unsigned long one;
unsigned short two;

long long one;


여러 개의 정수형이 필요한 이유

long형과 short형이 int형보다 더 많거나 더 적은 기억 공간을 '사용할 수도' 있다고 말했을까요? 그것은 C의 표준에서는 단순하게 short형이 int형보다 크지 않고, long형이 int형보다 작지 않다는 것만 보장하기 때문입니다. C가 이렇게 한 것은 데이터형을 기계에 맞추기 위해서입니다. Windows 3을 사용하던 시절에는 int형과 short형이 둘 다 16비트이고, long형은 32비트이었습니다. 그 후 Windows와 Apple 시스템은 short형을 16비트로, int형과 long형은 32비트로 사용하는 방법을 채택했습니다. 지금은 64비트 프로세서가 일반적으로 쓰이고 있어서 64비트 정수형에 대한 필요성이 생겨서 long long형이 만들어진 것입니다.

오늘날 PC에서 가장 일반적으로 사용되는 시스템은 long long형을 64비트, long형을 32비트, short형을 16비트로 설정하고, int형은 시스템 고유 워드 크기에 따라 16비트 또는 32비트로 설정하는 것입니다.

C 표준은 기본 데이터형의 최소 허용 크기를 정해놓고 있습니다. short형과 int형의 최소 범위는 16비트 단위에 해당하며, -32,767에서 32,767까지입니다.. long형의 최소 범위는 32비트 단위에 해당하며, -2,147,483,647에서 2,147,483,647까지입니다. unsigned short형과 unsigned int형의 최소범위는 0에서 65,535까지입니다. unsigned long형의 최소 범위는 0에서 4,294,967,295까지입니다. 64비트 필요성을 지원하기 위해 탄생한 long long형의 최소 범위는 -9,223,372,036,854,775,807에서 9,223,372,036,854,775,807까지입니다. unsigned long long형의 최소 범위는 0에서 18,446,744,073,709,551,615까지입니다.

왜 이렇게 많은 정수형이 있으며, 이 많은 정수형은 언제 사용할까요? 먼저 unsigned형에 대해 생각해봅시다. unsigned형은 음수가 없고, signed형보다 더 큰 범위의 양수를 가질 수 있으므로 수를 카운트할 때 사용하기 좋습니다.

long형은 int형으로는 다룰 수 없는 큰 수를 사용할 필요가 있을 때 사용합니다. 하지만 long형이 int형보다 큰 시스템에서는 long형을 사용하면 계산이 느려질 수 있어서 꼭 필요한 경우에만 사용해야 합니다. 만약, int형과 long형의 크기가 같은 시스템에서 32비트 정수들이 필요하다면 long형을 사용하는 것이 바람직합니다. int형을 사용했을 경우, 16비트 기계로 옮겼을 때 정상적으로 작동하지 않을 수 있기 때문입니다. 마찬가지로, 64비트 정수들이 필요하다면 long long형을 사용하면 됩니다.

int형이 32비트인 시스템에서 16비트 값이 필요하다면, 기억 공간 절약을 위해 short형을 사용하세요. 기억 공간을 절약하는 것은 중요합니다. 또한, short형을 사용하는 또 다른 이유는, 컴퓨터의 특정 구성 요소들에 의해 사용되는 하드웨어 레지스터들과 크기가 일치할 수 있기 때문입니다.


정수 오버플로우

만약, 자신에게 허용되는 최댓값보다 더 큰 수를 저장하려 한다면 무슨 일이 일어날까요? 정수형 변수를 최댓값으로 설정하고, 거기에 다른 수를 더한 후 무슨 일이 벌어지는지 확인해봅시다. 부호 있는 데이터형과 부호 없는 데이터형 두 가지의 경우를 모두 확인해 봅시다. (printf() 함수는 unsigned int 값을 출력하기 위해 %u 지정자를 사용합니다.)

/* big number.c -- int형의 최대 크기를 넘기는 프로그램 */
#include <stdio.h>
int main(void) {
    int i = 2147483647;
    unsigned int j = 4294967295;

    printf("%d \t %d \t %d \n", i, i + 1, i + 2);
    printf("%u \t %u \t %u \n", j, j + 1, j + 2);

    return 0;
}

위의 프로그램은 실행되는 환경에 따라 결과가 달라질 수 있습니다.

2147483647       -2147483648     -2147483647
4294967295       0       1

unsigned int형 변수 j는 자동차의 주행거리계와 비슷하게 작동합니다. 즉, 최댓값에 도달하면 처음부터 다시 시작합니다. int형 변수 i도 이와 비슷하기 행동합니다. 하지만, 둘은 차이가 있는데 unsigned int형 변수 j는 자동차의 주행거리계처럼 0에서 다시 시작하고, int형 변수 i-2147483648에서 다시 시작한다는 점입니다. 이렇게 동작할 때 i가 최댓값을 초과했다는 사실을 사용자에게 알리지 않는다는 것을 확인할 수 있습니다. 즉, 이와 같은 현상을 방지하는 장치를 프로그램에 미리 마련해두는 것이 좋습니다.


728x90
728x90