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;
short s;
int i;
long int li;
long l;
long long int lli;
long long ll;
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;
std::cout << "x was: " << x << std::endl;
x = x + 1;
std::cout << "x is now: " << x << std::endl;
return 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;
std::cout << "x was: " << x << std::endl;
x = x - 1;
std::cout << "x is now: " << x << std::endl;
return 0;
}
오버플로(overflow)는 정보가 손실되는 결과를 낳기 때문에 심각한 문제다. 변수가 범위를 벗어나는 갑을 저장해야 필요가 있는 경우 범위가 더 큰 변수를 사용해야 한다.
정수 나누기 (Integer division)
두 개의 정수를 나눌 때, C++은 결과가 정수라고 예상한다.
#include <iostream>
int main()
{
std::cout << 20 / 4;
return 0;
}
그러므로 결과가 소수라면 문제가 생긴다.
#include <iostream>
int main()
{
std::cout << 8 / 5;
return 0;
}
8/5의 정확한 결과는 1.6이지만 소수부(0.6)가 삭제되고 1의 결과가 나온다.
두 개의 정수로 나눗셈하면 C++은 정수 결과를 생성한다. 정수는 분수 값을 가질 수 없으므로 분수 부분은 반올림 하지 않고 단순히 떨어뜨린다.
정수 나누기를 사용할 때는 결과의 소수 부분이 손실되므로 주의해야 한다.
이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/24-integers/ 입니다.