2024. 2. 26. 14:32ㆍProgramming Language/C++
아래 링크 클릭 시 해당 본문으로 이동
자료형 (Data Type)
• 변수가 어떤 자료의 형태로 나타나는지 알려주는 역할을 하며, 타입(type) 또는 데이터 타입이라고도 표현한다.
▷ 예시
int i = 0;
// int → 자료형
// i → 변수이자 객체이다.
• 객체(Instance) : 내가 의도한 자료형의 실질적인 데이터
실체가 없던 자료형 `int`를 실제로 만들어낸 `i`가 바로 객체이다.
ex) 도장 = 자료형, 도장으로 찍어낸 것 = 객체
자료형 종류
• 무치형, 논리형, 정수형, 실수형
자료형 | 크기 (byte) | 범위 | |
무치형(Void Data Types) : 타입이 없을 때 사용한다. | |||
무치형 | void | - | - |
논리형 : 논리적인 값(true / false)을 나타낸다. | |||
논리형 | bool | 1 | 0 ~ 1 |
(signed) char, unsigned char → 문자형이지만 표현 방식이 정수형이다. | |||
문자형 | (signed) char | 1 | -128 ~ 127 |
unsigned char | 1 | 0 ~ 255 | |
wchar_t | 2 | 0 ~ 65,535 | |
정수형 | (signed) short | 2 | -32,768 ~ 32,767 ➜ 약 -3만 ~ 3만 |
(signed) short int | |||
unsigned short (int) | 2 | 0 ~ 65,535 ➜ 0 ~ 약 6만 |
|
(signed) int | 4 | -2,147,483,648 ~ 2,147,783,647 ➜ 약 -21억 ~ 21억 |
|
unsigned int | 4 | 0 ~ 4,276,967,295 ➜ 0 ~ 42억 |
|
(signed) long | 4 | -2,147,483,648 ~ 2,147,783,647 ➜ 약 -21억 ~ 21억 |
|
(signed) long int | |||
unsigned long (int) | 4 | 0 ~ 4,276,967,295 ➜ 0 ~ 42억 |
|
(signed) long long | 8 | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | |
(signed) long long int | |||
실수형 | float | 4 | ±3.4 × 10^(-37) ~ ±3.4 × 10^38 (7개의 자릿수) |
double | 8 | ±1.7 × 10^(-307) ~ ±1.7 × 10^308 (15개의 자릿수) | |
long double |
float vs. double
실수를 상수로 표현할 때 소수점 뒤 `f`의 유무에 따라 자료형이 달라진다.
• 상수 : 변하지 않는 수
• `f`를 붙이면 ➜ `float`
• `f`를 붙이지 않으면 ➜ `double`
data = 10.f / 3.f; // float
data = 10. / 3. // double
특별한 이유가 아니라면 같은 type끼리 연산하는 것이 좋다.
서로 다른 type끼리 연산하는 경우 컴파일러가 자동으로 변환해주긴 하지만, 타입 캐스팅으로 타입을 변환해 주는 것이 좋다.
• 타입 캐스팅(type casting, 형변환) : 변환할 대상(데이터) 앞에 명시적으로 `(자료형)`을 붙여서 타입을 변환해 주는 것
▷ 예시
// float형과 int형의 연산 결과를 float형 변수에 넣어야 되므로 int형인 30을 float으로 타입 캐스팅했다.
float b = 11.1234f + (float)30;
bit
• 메모리에 데이터를 저장할 때 쓰인다.
• 0과 1을 표현하는 최소 단위로, 더 이상 쪼갤 수 없다.
1byte = 8bit
ex) int : 4byte = 32bit
• KB, MB, GB, TB
◦ 2^10 = 1024byte = 1KB
◦ 1024KB = 1MB
◦ 1024MB = 1GB
◦ 1024GB = 1TB (= 2^40byte)
8bit(1byte)로 표현할 수 있는 경우의 수(가지 수) = 256가지
2가지 (0 또는 1) |
2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 |
한 bit당 2가지씩 8개이므로 2^8 = 256가지이다.
다른 정수형들의 경우의 수
• char(1byte) : 2^8 = 256가지
• short(2byte) : 2^8 x 2^8 = 2^16 = 65536가지 (unsigned가 아닌 그냥 short라면 범위는 대략 -3만 ~ 3만 정도이다.)
• int(4byte) : 2^32 (= 약 42억)
• long(4byte) : 2^32
• long long(8byte) : 2^64
• char
문자라는 뜻인 character의 약자로, 차 또는 캐릭터라고 읽는다.
나는 character의 약자이기 때문에 캐릭터라고 읽는다.
게임 개발할 때 자료형 때문에 문제가 생기는 경우
◦ 내가 표현할 수치의 데이터가 어느 정도면 충분한지를 생각해서 자료형을 선택해야 한다.
ex) RPG 게임
① A는 몬스터의 체력을 저장하는 int 타입의 공간이다.
② 몬스터가 대미지를 입거나 버프를 받으면 최대 체력을 20% 늘어나게 했다.
(몬스터 체력으로 표현할 수 있는 수는 int로 설정했기 때문에 약 -21억 ~ 21억)
③ 처음에는 몬스터 체력이 21억을 넘을 것이라는 것을 생각하지 못했다.
(플레이어들이 공격했을 때의 대미지가 처음에는 200 ~ 300 정도 됐었는데 게임이 오랫동안 유지되면서 9000만, 10억이 되어버렸다.)
④ 몬스터 체력이 약 21억(int)까지 늘어난 상태에서 체력 버프 20%를 받는데, 그 순간 음수가 되어버려서 갑자기 죽어버린다.
int가 32bit인데 맨 앞 bit가 1이 되면 signed에서는 음수로 인식하기 때문이다.
8bit로 표현한 값
• 각각의 bit값이 1일 때의 값
2^7 = 128 |
2^6 = 64 |
2^5 = 32 |
2^4 = 16 |
2^3 = 8 |
2^2 = 4 |
2^1 = 2 |
2^0 = 1 |
8bit로 0~2를 표현하면 아래와 같다.
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
= 0
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
= 2^0 = 1
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
= 2^1 = 2
우리가 평소에 사용하는 10진수와 비슷하다.
10^3 = 1000 | 10^2 = 100 | 10^1 = 10 | 10^0 = 1 |
1. 정수형 자료형
signed | unsigned |
• 양수, 음수 표현 • 생략 가능 (보통은 생략한다.) |
• 양수만 표현 |
일반적으로 자료형 앞에 아무것도 붙이지 않으면 signed를 의미하는데, 컴파일러에 따라서 기본값이 unsigned일 수도 있다.
▷ 예시 (char)
char c1 = 0; // signed char c1 = 0;
unsigned char c2 = 0;
`c1` ➜ 양수, 음수를 표현하는 공간이 만들어진다.
`c2` ➜ 양수만 표현하는 공간이 만들어진다.
양수만 표현할 때 (1byte)
1) 경우의 수 : 256가지
2) 표현 가능한 값 : 0~255
2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 |
▷ 1byte 정수형 unsigned 변수에 256을 저장했을 때
unsigned char c2 = 0;
c2 = 256; // 0'\0'
// '\0'은 숫자 0에 해당하는 ASCII 문자이다.
// char는 표현 방식은 정수형이지만 문자를 나타내는 것이 목적인 문자 자료형이므로 정수를 저장하면 문자도 같이 저장된다.
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
= 255
+1
1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
= 256
255의 2진수에 1을 더해서 `1 0000 0000`이 나왔어도 char은 1byte(8bit)이기 때문에 맨 앞에 있는 1은 버려지므로 0이 된다.
양수, 음수 둘 다 표현할 때 (1byte)
1) 경우의 수 : 256가지
2) 표현 가능한 값 : -128~127
[-1~-128 : 128개] + [0~127 : 128개]
MSB(Most Significant Bit, 가장 중요한 비트)
• 최상위 비트로, 맨 앞의 첫 번째 비트트는 부호를 표시하기 위해 사용한다.
1) 맨 앞 비트 = 0 → 양수
0 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 |
표현 가능한 값 : 0 ~ 127
2) 맨 앞 비트 = 1 → 음수
1 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 | 2가지 |
표현 가능한 값 : -1 ~ -128
Q. 맨 앞 비트가 1이면 음수라고 했는데, 1을 2진수로 나타낸 `0000 0001`에서 맨 앞 bit만 1로 바꾸면 -1이 될까?
A. 결론부터 말하면 아니다.
음수 찾기 (1의 보수, 2의 보수)
※ 음수 찾는 간단한 방법
• 비트를 반전시키고(1을 0으로, 0을 1로 = 1의 보수) 1을 더하면(2의 보수) 된다.
1의 보수는 +0(`0000 0000`)과 -0(`1111 1111`)이 존재하기 때문에 논리적으로 맞지 않다.
2의 보수에서는 +0(`0000 0000`)의 비트를 반전시키고 1을 더하면 다시 `0000 0000`이 되기 때문에 -0은 존재하지 않는다.
2의 보수는 덧셈 연산에서 발생하는 오버플로우 처리가 1의 보수 형식보다 간단하며, 컴퓨터 시스템에서 실제로 사용하는 형식이다.
• 오버플로우(overflow) : 이진 연산에서 덧셈이나 뺄셈 연산의 결과가 주어진 비트 수로 표현할 수 있는 범위를 초과하는 경우를 말한다.
1의 보수와 2의 보수로 음수 찾는 과정
▷ +1과 -1 (1byte)
1) 1의 보수
• 2진수 자릿수값이 모두 1인 수 - 변환하고자 하는 2진수
// 1의 1의 보수
1111 1111
- 0000 0001
=============
1111 1110
◦ +1 : `0000 0001`
◦ -1(1의 1의 보수) : `1111 1110`
2) 2의 보수
• `1의 보수값 + 1`
// 1의 2의 보수
1111 1110
+ 1
=============
1111 1111
// +1 비트값과 -1 비트값을 더해서 0이 나오는지 확인
0000 0001
+ 1111 1111
=============
0000 0000
◦ +1 : `0000 0001`
◦ -1(1의 2의 보수) : `1111 1111`
여기서 알 수 있는 사실 2가지
① 1의 보수와 2의 보수의 양수 표현은 같지만 음수 표현은 다르다.
② 무조건 맨 앞 비트를 0에서 1로 바꾼다고 해서 해당 값의 음수가 되는 것은 아니다.
같은 비트여도 보는 관점에 따라서 해석이 달라진다.
1111 1111
• 양수의 관점(unsigned char) = 255
• 음수의 관점(char) = -1
컴퓨터 입장에서 `1111 1111`는 8개의 비트가 전부 1로 채워진 비트이다.
하지만 보는 관점이 양수일 때는 255으로, 음수일 때는 -1으로 해석된다.
가족을 예로 들었을 때, 내 입장에서 아빠지만 할아버지 입장에서 아빠는 아들인 것처럼 사람 자체는 달라지지 않았지만 누구의 관점이냐에 따라 다르게 해석된다.
char vs. unsigned char
// 255 대입
char c1 = 0;
c1 = 255; // -1
unsigned char c2 = 0;
c2 = 255; // 255
// -1 대입
char c1 = 0;
c1 = -1; // -1
unsigned char c2 = 0;
c2 = -1; // 255
2. 실수형 자료형
• 정수 표현 방식 ≠ 실수 표현 방식
• bit 상태값 : 정수형 ≠ 실수형
ex) 3 ≠ 3.0
정수 표현 방식은 소수점으로 표현할 수 없다.
실수 안 할 자신 있고 쓰는 의도를 정확히 파악한 것이 아니면 정수와 실수를 섞어서 쓰는 것은 지양해야 한다.
부동 소수점 | 고정 소수점 | |
설명 | • 컴퓨터에서 실수를 표현할 때 소수점의 위치를 고정하지 않는 것 소수점이 움직인다고 생각하면 된다. • 고정 소수점에 비해 표현 가능한 값의 범위가 넓다. |
• 소수점이 움직이지 않고 고정되어 있는 것 |
ex) 12.34
고정 소수점 : 12.34
부동 소수점 : 1.234 x 10 = 0.1234 x 10^2 = 0.01234 x 10^3 = 0.001234 x 10^4 = …
위 내용의 32비트 실수는 float이다. (float : 4byte = 32bit)
▷ 21.8125
21의 2진수 ➜ `10101`
10진수 → 2진수 변환
변환하려는 값을 몫이 1이 되어 더 이상 나눠지지 않을 때까지 2로 나눈다.
몫인 1과 나머지 숫자(0 또는 1)를 역순으로 합치면 된다.
0.8125의 2진수 ➜ `0.1101`
10진법 : 0.1에서 1이 되려면 1/10이 10개 모여야 한다. (= 0.1이 10개 모여야 한다.)
2진법 : 0.1에서 1이 되려면 1/2이 2개 모여야 한다. (= 0.5가 2개 모여야 한다.)
0.1 x 10개(진수) = 0.5 x 2개(진수) = 1로 생각하기
소수점 아래 값 - 10진수 vs. 2진수
1) 10진수
소수점 (10진수) | 음수 지수 |
0.1 | 10^(-1) |
0.01 | 10^(-2) |
0.001 | 10^(-3) |
0.0001 | 10^(-4) |
2) 2진수
10진수와 달리 아래 표의 `0.0001` ~ `0.1`은 비트를 뜻한다.
비트 (2진수) | 음수 지수 (10진수) | 소수점 (10진수) |
`0.1` | 2^-1 | 0.5 |
`0.01` | 2^-2 | 0.25 |
`0.001` | 2^-3 | 0.125 |
`0.0001` | 2^-4 | 0.625 |
2진수 `0.1101`이 0.8125인지 확인 ➜ 0.5 + 0.25 + 0 + 0.625 = 0.8125
정규화
• 소수점을 맨 앞으로 보내고 2의 n제곱을 곱해준다.
10진법에서 소수점을 맨 앞으로 보내고 10의 n제곱을 곱한 것처럼 2진법도 같은 방식이다.
ex) 10진수 : 10000 = 0.1 x 10^5 / 2진수 : `111` = 0.111 x 2^3
`10101.1101`을 정규화하기 위해 소수점을 맨 앞으로 보낸다.
이때 소수점이 5칸 앞으로 갔기 때문에 5 제곱을 곱해줘야 되는데, 2진수이기 때문에 `0.101011101`에 2^5를 곱한다.
∴ `10101.1101` = 0.101011101 x 2^5
부동소수점 표현
• 지수 : 거듭제곱 부분
• 가수 : 밑에 있는 숫자
[32bit] 21.8125 ➜ 정규화 = 0.101011101 x 2^5
[1bit] 맨 앞 bit 부호 ➜ 양수 = 0
[8bit] 지수 부호 = 0, 지수 5를 2진수로 = 0000101
[32 - 1 - 8 = 23bit] 가수 ➜ 0.101011101에서 소수점 뒷부분을 그대로 적어주고 나머지는 0으로 채운다. = 101011101 00000000000000
∴ 00000010110101110100000000000000
실수가 소수점으로 딱 떨어지지 않을 때
소수점 아래 부분이 점점 늘어나다 보면 가수 부분 자리가 모자라는 경우가 발생한다. (ex. 3.1231542…)
가수 부분은 무한정 길어질 수 없기 때문에 가장 근사한 값으로 비트를 잡아줘야 한다.
double의 메모리 길이가 float의 2배이기 때문에 아랫 단위의 미세한 소수점까지 훨씬 더 정밀하게 표현 가능하다.
※ 요약
• 실수 표현 방식은 정밀도에 의존한다.
• double ➜ float보다 더 아래 부분의 소수점 자리까지 정밀하게 표현 가능하다.
◦ 실수가 정밀하게 표현되지 않아서 발생하는 문제 (ex. 조건식)
어떤 결괏값이 실수 `1`일 때 내가 원하는 상황을 실행시키는 조건을 만들었다고 해보자.
결괏값이 `1`이 나와줘야 되고 내가 봤을 때는 `1`인데 테스트를 해보니 `0.9999998f`가 나온다.
사실상 거의 `1`인데도 내가 걸었던 조건은 정확하게 실수 표현 방식으로 `1`이 나와야 된다고 했기 때문에 해당 조건이 걸리지 않는 경우가 생긴다.
'Programming Language > C++' 카테고리의 다른 글
[C++] 함수[main()], return, void (0) | 2024.03.03 |
---|---|
[C++] 메모리 영역, 변수 (0) | 2024.03.02 |
[C++] 조건문(Conditional Statements), 삼항 연산자 (0) | 2024.02.29 |
[C++] 연산자(Operators), 전처리기[#define], 연산자 우선순위 (0) | 2024.02.29 |
[C++] STL, 스택(Stack), 큐(Queue) (0) | 2024.02.26 |