콘텐츠로 이동

정수 타입 (Integer Types)

C++의 내장 정수 타입 중 사용하는 것은 int 하나뿐입니다. 프로그램에 다른 크기의 정수 타입이 필요하다면 <stdint.h>의 정확한 너비 정수 타입, 예를 들어 int16_t를 쓰세요. 값이 2^31 이상이 될 수 있다면 int64_t 같은 64비트 타입을 쓰세요. 값 자체는 int에 담기 지나치게 크지 않더라도, 더 큰 타입이 필요한 중간 계산에 쓰일 수 있다는 점을 유념하세요. 애매하면 더 큰 타입을 고르세요.

정의:

C++는 int 같은 정수 타입의 정확한 크기를 규정하지 않습니다. 요즘 아키텍처에서 흔한 크기는 short가 16비트, int가 32비트, long이 32비트 또는 64비트, long long이 64비트지만, 플랫폼마다 선택이 다르며 특히 long이 그렇습니다.

장점:

선언의 통일성.

단점:

C++에서 정수 타입의 크기는 컴파일러와 아키텍처에 따라 달라질 수 있습니다.

결정:

표준 라이브러리 헤더 <stdint.h>는 int16_t, uint32_t, int64_t 같은 타입을 정의합니다. 정수의 크기를 보장받아야 할 때는 short나 unsigned long long 같은 것들보다 항상 이 타입들을 우선해서 쓰세요. 내장 정수 타입 중에서는 int만 써야 합니다. 적절한 경우라면 size_t나 ptrdiff_t 같은 표준 타입 별칭을 얼마든지 써도 좋습니다.

우리는 루프 카운터처럼 너무 커지지 않는다는 것을 아는 정수에 int를 아주 자주 씁니다. 그런 용도에는 그냥 평범한 int를 쓰세요. int가 최소 32비트라고 가정해도 되지만, 32비트보다 크다고 가정하지는 마세요. 64비트 정수 타입이 필요하다면 int64_t나 uint64_t를 쓰세요.

"클" 수 있다는 것을 아는 정수에는 int64_t를 쓰세요.

uint32_t 같은 부호 없는 정수 타입은 쓰지 말아야 합니다. 숫자가 아니라 비트 패턴을 표현한다든가 2^N에 대한 모듈러 오버플로 동작이 필요하다든가 하는 타당한 이유가 있을 때는 예외입니다. 특히 어떤 수가 결코 음수가 되지 않는다는 것을 말하려고 부호 없는 타입을 쓰지 마세요. 그런 용도에는 어서션을 쓰세요.

표준 라이브러리 정수 타입에는 std:: 접두사를 생략하는 편을 선호하세요. 다섯 글자를 더 적는 것이 그만큼의 군더더기를 감수할 값어치가 없습니다.

여러분의 코드가 크기를 반환하는 컨테이너라면, 그 컨테이너를 어떻게 쓰더라도 감당할 수 있는 타입을 쓰도록 하세요. 애매하면 작은 타입보다 큰 타입을 쓰세요.

정수 타입을 변환할 때는 주의하세요. 정수 변환과 승격은 정의되지 않은 동작을 일으켜 보안 버그를 비롯한 여러 문제로 이어질 수 있습니다.

부호 없는 정수에 대하여

부호 없는 정수는 비트 필드와 모듈러 산술을 표현하는 데 적합합니다. 역사적인 우연으로 C++ 표준은 컨테이너의 크기를 나타내는 데에도 부호 없는 정수를 씁니다. 표준화 위원회의 많은 사람들이 이것을 실수라고 여기지만, 이 시점에서 고치는 것은 사실상 불가능합니다. 부호 없는 산술이 단순한 정수의 동작을 본뜨지 않고, 표준에 의해 모듈러 산술(오버플로·언더플로 시 순환)을 본뜨도록 정의되어 있다는 사실은, 상당한 부류의 버그를 컴파일러가 진단할 수 없다는 것을 뜻합니다. 다른 경우에는 그 정의된 동작이 최적화를 방해합니다.

그렇다고는 해도, 정수 타입의 부호 유무를 섞는 것 역시 그에 못지않게 큰 부류의 문제를 일으킵니다. 우리가 줄 수 있는 최선의 조언은 이렇습니다. 포인터와 크기 대신 반복자와 컨테이너를 쓰려고 하고, 부호 유무를 섞지 않으려고 하고, (비트 필드나 모듈러 산술을 표현하는 경우가 아니라면) 부호 없는 타입을 피하려고 하세요. 변수가 음수가 아님을 주장하려는 목적만으로 부호 없는 타입을 쓰지 마세요.


옮긴이 풀이

핵심: 기본은 int, 정확한 크기가 필요하면 <cstdint>

내장 정수 타입 중 평소엔 int만 쓰세요. C++ 표준은 int/long 등의 정확한 크기를 보장하지 않지만, int는 최소 32비트라고 가정해도 됩니다(그 이상은 가정 금지).

크기가 중요할 때

  • 정확한 너비가 필요하면 <cstdint>의 int16_t, uint32_t, int64_t 등을 쓰세요.
  • 값이 2³¹ 이상일 수 있으면 int64_t 같은 64비트 타입. 중간 계산에서 커질 수 있다는 점도 고려하세요. 애매하면 큰 타입.
  • size_t, ptrdiff_t 같은 표준 별칭은 적절히 사용. 표준 정수 타입에선 std:: 접두사를 생략해도 됩니다.

부호 없는(unsigned) 타입을 피하라

uint32_t 같은 부호 없는 타입은 비트 패턴이나 모듈러 산술을 표현할 때만 쓰세요. "음수가 될 수 없다"는 이유로 쓰지 마세요(그건 어서션으로). 부호 없는 산술은 오버플로 시 순환(wrap)으로 정의되어, 컴파일러가 못 잡는 버그를 만듭니다. 부호 유무를 섞는 것도 문제이니, 포인터+크기 대신 반복자+컨테이너를 쓰는 편이 낫습니다.