02.04 - 정수 (integer)
정수(integer)형 변수는 소수가 아닌 숫자(ex: -2, -1, 0, 1, 2)만 저장할 수 있는 변수다. C++ 에는 다섯 가지 기본 정수 자료형이 있다.
Category | Type | Minimum Size | Note |
---|---|---|---|
character | char | 1 byte | |
integer | short | 2 bytes | |
int | 2 bytes | Typically 4 bytes on modern architectures | |
long | 4 bytes | ||
long long | 8 bytes | C99/C++11 type |
char는 문자 및 정수 모두에 속하는 특수한 자료형이다.
다양한 정수 자료형 간의 주요 차이점은 크기가 다양하다는 것이다. 더 큰 정수 자료형은 더 큰 숫자를 저장할 수 있다. C++은 정수가 특정 크기를 가지지 않고 특정 최소 크기만 가질 것을 보장한다. 각 자료형의 크기는 sizeof
연산자를 사용해 알 수 있다.
정수 변수 선언하기 (Defining integers)
char c;
short int si; // valid
short s; // preferred
int i;
long int li; // valid
long l; // preferred
long long int lli; // valid
long long ll; // preferred
short int
, long int
그리고 long long int
는 유효한 정수 자료형이지만, 짧은 버전인 short
, long
및 long long
을 주로 사용한다. 접두어 int
를 추가하면 입력이 늘어나고 int
자료형과 헷갈려 실수로 이어진다.
정수 범위와 부호 (Integer ranges and sign)
이전 포스트에서 n bit의 변수는 2^n 개의 다른 값을 저장할 수 있다. 정수 변수가 값을 저장할 수 있는 범위는 크기(bit)와 부호(부호가 있는지 없는지)에 따라 다르다.
부호 있는(signed) 정수는 음수와 양수를 모두 저장할 수 있는 변수다. signed
키워드를 이용해서 명시적으로 부호 있는 정수를 선언할 수 있다.
signed char c;
signed short s;
signed int i;
signed long l;
signed long long ll;
1 byte의 부호 있는 정수의 범위는 -128 ~ 127이다. 그러므로 -128에서 127 사이의 값은 1byte 부호 있는 정수 자료형에 안전하게 넣을 수 있다.
변수를 사용하여 무언가의 양이나 크기를 저장하는 경우, 음수가 필요 없다는 것을 알 수 있다. 부호 없는(unsigned) 정수는 양수 값만 가질 수 있는 정수다. unsigned
키워드를 이용해서 명시적으로 부호 없는 정수를 선언할 수 있다.
unsigned char c;
unsigned short s;
unsigned int i;
unsigned long l;
unsigned long long ll;
1 byte의 부호 없는 정수의 범위는 0 ~ 255이다. 변수를 부호 없는 것으로 선언하며 음수를 저장할 수 없지만 두 배의 양수를 저장할 수 있다.
Size/Type | Range |
---|---|
1 byte signed | -128 to 127 |
1 byte unsigned | 0 to 255 |
2 byte signed | -32,768 to 32,767 |
2 byte unsigned | 0 to 65,535 |
4 byte signed | -2,147,483,648 to 2,147,483,647 |
4 byte unsigned | 0 to 4,294,967,295 |
8 byte signed | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
8 byte unsigned | 0 to 18,446,744,073,709,551,615 |
수학적으로 n bit 부호 변수의 범위는 -(2 ^ (n-1)) ~ 2^(n-1)-1이다. n bit의 부호 없는 변수의 범위는 0 ~ 2^n - 1이다.
Overflow
자료형의 범위를 벗어나는 숫자를 변수에 넣으려고 하면 어떻게 될까? 변수가 값을 저장하기에 충분한 메모리를 할당하지 않아 비트가 손실되면 오버플로(overflow)가 발생한다.
2 진수(binary)에서 각 숫자가 0 또는 1의 값만 가질 수 있다. 아래 그림은 0에서 15까지를 보여준다.
Decimal Value | Binary Value |
---|---|
0 | 0 |
1 | 1 |
2 | 10 |
3 | 11 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
11 | 1011 |
12 | 1100 |
13 | 1101 |
14 | 1110 |
15 | 1111 |
보다시피 큰 숫자일수록 더 많은 bit를 나타낸다. 변수는 고정된 비트 수를 가지고 있으므로, 데이터를 저장하는데에 한계가 있다.
4 bit만 저장할 수 있는 가상의 부호 없는 변수를 생각해보자. 위의 표에 열거된 이진수 값들은 모두 4 bit보다 크지 않기 때문에 변수에 편안하게 할당된다.
그러나 변수에 4 bit를 초과하는 값을 할당하려고 하면 오버플로가 발생한다. 최하위 bit 4개만 저장하고 초과 비트는 손실된다.
예를 들어, 4 bit 변수에 10진수 값 21을 넣으려고 하면:
Decimal Value | Binary Value |
---|---|
21 | 10101 |
21은 5 비트 '10101'이다. 4개의 오른쪽 비트 '0101'이 변수에 들어가고 가장 왼쪽 비트 '1'은 손실된다. 결국에 변수에 10 진수 값인 5('0101')가 저장된다.
실제 코드가 사용된 예제:
#include <iostream>
int main()
{
unsigned short x = 65535; // largest 16-bit unsigned value possible
std::cout << "x was: " << x << std::endl;
x = x + 1; // 65536 is out of our range -- we get overflow because x can't hold 17 bits
std::cout << "x is now: " << x << std::endl;
return 0;
}
// x was: 65535
// x is now: 0
unsigned short
자료형의 범위는 0 ~ 65,535다. 65,535는 부호 없는 2byte(16 - bit) 정수가 보유할 수 있는 최대값이다. 값에 1을 더하면 새로운 값 65,536이 되어야 하지만 65,536은 17 비트인 '1 0000 0000 0000 0000'로 표현된다. 결과적으로 최상위 비트 '1'이 손실되고 하위 16 비트 '0000 0000 0000 000'인 숫자 0이 할당된다.
오버플로를 반대로 할 수도 있다.
#include <iostream>
int main()
{
unsigned short x = 0; // smallest 2-byte unsigned value possible
std::cout << "x was: " << x << std::endl;
x = x - 1; // overflow!
std::cout << "x is now: " << x << std::endl;
return 0;
}
// x was: 0
// x is now: 65535
오버플로(overflow)는 정보가 손실되는 결과를 낳기 때문에 심각한 문제다. 변수가 범위를 벗어나는 갑을 저장해야 필요가 있는 경우 범위가 더 큰 변수를 사용해야 한다.
정수 나누기 (Integer division)
두 개의 정수를 나눌 때, C++은 결과가 정수라고 예상한다.
#include <iostream>
int main()
{
std::cout << 20 / 4;
return 0;
}
// 5
그러므로 결과가 소수라면 문제가 생긴다.
#include <iostream>
int main()
{
std::cout << 8 / 5;
return 0;
}
// 1
8/5의 정확한 결과는 1.6이지만 소수부(0.6)가 삭제되고 1의 결과가 나온다.
두 개의 정수로 나눗셈하면 C++은 정수 결과를 생성한다. 정수는 분수 값을 가질 수 없으므로 분수 부분은 반올림 하지 않고 단순히 떨어뜨린다.
정수 나누기를 사용할 때는 결과의 소수 부분이 손실되므로 주의해야 한다.
이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/24-integers/ 입니다.
'C++ 이야기 > 02. 기본 자료형' 카테고리의 다른 글
C++ 02.06 - 부동 소수점 숫자 (floating point numbers) (1) | 2018.06.25 |
---|---|
C++ 02.05 - 고정된 너비 정수 (fixed-width integers) (0) | 2018.06.24 |
C++ 02.03 - 변수 크기와 sizeof 연산자 (2) | 2018.06.24 |
C++ 02.02 - void (0) | 2018.06.24 |
C++ 02.01 - 자료형과 변수 정의의 기본 (The basis of data type and variable definition) (1) | 2018.06.24 |