C++에서 사용하는 데이터 형식
1. 데이터 형식
변수는 '값을 저장할 수 있는 공간'
C++ 언어에서는 변수에 값을 저장하기 전에 정수, 부동 소수점, 문자 등 어떤 값을 저장할지 미리 정해주어야함
이를 데이터 형식(자료형)이라고 한다
파이썬 같은 인터프리터 언어는 변수의 형식을 자동으로 결정해주는데 C++같은 컴파일 언어는 형식을 직접 지정해주어야함
형식이 엄격한 C++같은 언어는 변수를 선언하고 사용할 때 어떤 형식으로 만들지 항상 고민해야하는데,
파이썬같은 형식이 유연한 언어보다 훨씬 까다롭지만, 런타임 오류도 줄고 메모리를 효율적으로 이용할 수 있는 장점도 있다
형식 | 키워드 | 크기(byte) | 특징 |
보이드 | void | none | '형식 없음' |
불리언 | bool | 1 | true, false |
문자 | char | 1 | 8비트 정수형으로 사용될 경우 일반적으로 -128~127 |
unsigned char | 1 | 0~255 | |
signed char | 1 | 부호 비트를 가지도록 명시적으로 표현 | |
char8_t | 1 | C++20 새 형식 | |
char16_t | 2 | UTF-16 문자 표현에 사용 | |
char32_t | 4 | UTF-32 문자 표현에 사용 | |
wchar_t | 2 | 와이드 문자(wide char) 표현 | |
__wchar_t | 2 | 마이크로소프트 전용 | |
정수 | short | 2 | 적어도 char보다는 크기가 큰 정수 |
unsigned short | 2 | 양수만 저장 | |
int | 4 | 일반적으로 가장 많이 사용 | |
unsigned int | 4 | 양수만 | |
__int8 | 1 | 마이크로소프트 전용 정수 __int8은 char과 동일 취급 __int16은 short, __int32는 int, __int64는 long long와 같은 데이터 형식 취급 |
|
__int16 | 2 | ||
__int32 | 4 | ||
__int64 | 8 | ||
long | 4 | long의 경우 32비트 운영체제에서는 4byte, 64비트 운영체제에서는 8byte 윈도우 64비트에서는 long도 4byte |
|
unsigned long | 4 | 양수만 | |
long long | 8 | int형 연산에서 초과되는 범위를 다룰때 사용하고 적어도 8byte 이상 크기 보장 | |
unsigned long long | 8 | 양수만 | |
부동 소수점 | float | 4 | C++언어에서 가장 작은 부동 소수점 |
double | 8 | float보다 큰 부동 소수점 형식, 소수를 구하는 연산에서는 double이 소수점 아래 표현을 더 많이 할 수 있어 double 추천 | |
long double | 8 | GCC, G++에서 long double는 16byte |
__int8. __wchar_t 처럼 데이터 형식 앞에 __이 붙으면 마이크로소프트에서 제공하는 확장형
마이크로소프트 비주얼 C++에서만 인식
특정 환경에서만 지원되므로 호환성이 떨어질 수 있어 int8_t, wchar_t같은 표준 C++ 자료형을 사용하는 것을 추천
2. void
void는 형식이 없음을 뜻함
그래서 void value;처럼 선언할 수 없음

1) 함수가 값을 반환하지 않음을 표시할 때
다음 print_func()는 값을 반환하는 return이 없는데, 반환값이 없는 함수를 선언할 때 void를 표시함
void print_func() {
std::cout << "func" << std::endl;
}
2) 함수의 매개변수가 없음을 표시할 때
함수의 매개변수가 없으면 print_func()처럼 아무것도 입력하지 않은 채 ()처럼 빈 괄호로 두어도 된다.
하지만 input_func(void)처럼 명시적으로 표현할 수 있다
int input_func(void) {
int input_value;
std::cin >> input_value;
return input_value;
}
3) 모든 자료형을 가리킬 수 있는 제네릭 포인터(generic pointer)
어떤 변수라도 가리킬 수 있는 제네릭 포인터를 만들 때 사용가능
제네릭 포인터에서 void는 단순히 '형태가 없음'이라기 보다는 '형태가 자유로움'을 의미함
int main() {
int int_value;
float float_value;
void *ptr_value; //제네릭 포인터
ptr_value = &int_value;
ptr_value = &float_value;
return 0;
}
3. bool
bool은 참(true, 1)과 거짓(false, 0)만 가질 수 있다
bool형 변수에 true,false를 넣어 초기화할 수 있지만, 실제로는 1,0 정수로 저장된다
#include <iostream>
using namespace std;
int main(){
bool value;
value = true;
cout << value << endl;
value = false;
cout << value << endl;
return 0;
}

4. 문자 형식
char은 C++에서 문자를 다룰 때 사용하는 대표적인 데이터 형식이지만 8bit 정수를 저장하는 역할을 할 뿐
문자 전용 데이터 형식은 아니다.
char에 저장된 값은 아스키 코드로 변환하여 사용할 수 있다

문자로 출력할 수 있는 것은 32~126번
#include <iostream>
using namespace std;
int main(){
cout << "아스키 코드 출력하기 [32 ~ 126]:\n";
for (char i = 32; i <= 126; i++) { //32부터 126까지 1씩 증가하며 반복
//아스키 코드를 출력할 때 공백을 넣고 16개마다 줄 바꾸기
cout << i << ((i % 16 == 15) ? '\n' : ' ');
}
return 0;
}

문자를 표현하는 데 char을 사용하는 이유는 아스키코드가 7bit 형태의 체계를 따르기 때문
나머지 1bit는 통신 확인용 패리티 비트
char이 아스키 문자를 저장할 때는 0 ~ 127사이 값을 가진다
만약 char을 8bit 정수 저장용으로 사용한다면 1bit를 부호로 사용하여 -128~127을 저장
unsigned char은 부호 비트까지 써서 0~255까지 저장

wchar_t는 와이드 문자를 저장하는 자료형
비주얼 스튜디오에서는 wchar_t를 2byte로 정의하고 GCC 컴파일러는 4byte로 정의
하지만 GCC에서도 컴파일할 때 -fshort-wchar 옵션을 적용해서 wchar_t를 2byte로 사용가능
구분 | char | wchar_t |
인코딩 | 멀티바이트(MBCS) | 유니코드(UNICODE) |
단일 문자 크기 | 1byte 또는 2byte (영문 숫자 등의 아스키 코드는 1byte, 한글, 한자 등은 2byte로 표현) |
2byte(GCC에서는 기본 4byte) |
문자열 | 유니코드를 제외한 문자열(ANISI, UTF-8) | 와이드 문자, UTF-16으로 인코딩된 문자열 |
UTF-16으로 인코딩된 문자열을 직접 출력해본다.
wchar_t 문자열을 출력할 때는 wcout을 이용해야한다.
또한 유니코드 문자열을 넣으려면 L"문자열"처럼 지정해야한다
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main(){
wchar_t message_korean[] = L"반갑다 세계야!";
wchar_t message_chinese[] = L"很高兴认识你世界!";
wchar_t message_japanese[] = L"うれしい世界だ!";
wchar_t message_russian[] = L"Приятно познакомиться, мир!";
cout << "Hello, World!" << endl;
_setmode(_fileno(stdout), _O_U16TEXT); //윈도우 콘솔 창 유니코드 출력 모드 설정
wcout << message_korean << endl;
wcout << message_chinese << endl;
wcout << message_japanese << endl;
wcout << message_russian << endl;
return 0;
}

5. 정수 형식
일반적으로 가장 많이 사용하는 데이터 형식
양의 정수, 음의 정수, 0
정수형은 다른 데이터 형식과는 다르게 조금 특이하게 설정
int는 시스템의 자연스러운 크기를 따르도록 규정
여기서 자연스러운 크기는 시스템에서 한번에 처리할 수 있는 크기로, 그러므로 시스템에 따라 int는 크기가 다르다
16bit 시스템에서 int는 16bit이고 32bit에서는 32bit이다.
그런데 현재 거의 기본으로 출시되고 있는 64bit컴퓨터에서는 실제로 int는 32bit라고함(4byte)
sizeof(데이터형)을 쓰면 해당 데이터형식의 크기를 알 수 있다
#include <iostream>
using namespace std;
int main(){
cout << "short : " << sizeof(short) << " bytes" << endl;
cout << "unsigned short : " << sizeof(unsigned short) << " bytes" << endl;
cout << "int : " << sizeof(int) << " bytes" << endl;
cout << "unsigned int : " << sizeof(unsigned int) << " bytes" << endl;
//MS 전용
cout << "__int8 : " << sizeof(__int8) << " bytes" << endl;
cout << "__int16 : " << sizeof(__int16) << " bytes" << endl;
cout << "__int32 : " << sizeof(__int32) << " bytes" << endl;
cout << "__int64 : " << sizeof(__int64) << " bytes" << endl;
cout << "long : " << sizeof(long) << " bytes" << endl;
cout << "unsigned long : " << sizeof(unsigned long) << " bytes" << endl;
cout << "long long : " << sizeof(long long) << " bytes" << endl;
cout << "unsigned long long : " << sizeof(unsigned long long) << " bytes" << endl;
return 0;
}

__int8같은 데이터형식은 마이크로소프트 비주얼 C++ 컴파일러에서만 동작
다른 환경에서는 int8_t같이 수정해야함
C++ 언어 표준안은 정수형의 크기를 명시하지는 않지만, 기본적으로 다음과 같다
1byte = char <= short <= int <= long <= long long
정수형에서 signed는 음수, 양수를 모두 저장할 수 있다.
unsigned는 양수만 저장 가능하다
nbit signed는 -2^(n-1) ~ 2^(n-1)
nbit unsigned는 0 ~ 2^(n)-1
1byte는 당연히 8bit
예시:
1byte signed : -128 ~ 127
1byte unsigned: 0 ~ 255
2byte signed: -32768 ~ 32767
4byte signed : -2147483648 ~ 2147483647
6. 부동소수점
부동이란 "떠다니며 움직인다"라는 뜻으로, 소수점이 고정되지 않고 움직인다는 뜻
소수점이 움직인다는 것은 정수부와 소수부의 자릿수가 일정하지 않다는 의미
그러나 유효숫자의 자릿수는 정해져있다
자료형의 크기가 정해져있으므로 부동소수점의 특정자리까지만 저장할 수 있고 나머지는 유실
부동소수점의 정밀도란, 데이터 유실 없이 얼마나 많은 유효 자릿수를 나타낼수 있는지를 말한다
#include <iostream>
using namespace std;
int main(){
cout << 9.87654321f << endl;
cout << 987654.321f << endl;
cout << 9876543.21f << endl;
cout << 0.00000987654321f << endl;
cout << 0.00000000000987654321f << endl;
return 0;
}

실행결과는 6자리만 출력되는 것을 알 수 있다
cout은 부동소수점 출력할 때 기본 정밀도가 6으로 설정되어있다.
6자리까지만 유효하고 나머지는 생략함
C++언어의 부동소수점은 IEEE754에서 정의한 형식으로 정의
최상위 비트는 부호를 나타내고, 지수와 가수로 나뉨

부동소수점은 고정소수점보다 넓은 범위의 수를 나타내 계산에 많이 이용되나,
근삿값으로 표현되고 고정소수점 방식보다 연산속도가 느려 별도의 연산장치가 필요함
C++에서 숫자 뒤에 f를 붙이면 float, l을 붙이면 long double, 아무것도 붙이지 않으면 double
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
float float_value = 9.87654321f;
double double_value = 9.87654321987654321;
long double long_double_value = 9.87654321987654321l;
cout << "float : " << sizeof(float) << " bytes" << endl;
//유효자릿수만큼 정밀도 조정
//setprecision(numeric_limits<float>::digits10 + 1)
cout << "float_value : " <<
setprecision(numeric_limits<float>::digits10 + 1) <<
float_value << endl << endl;
cout << "double : " << sizeof(double) << " bytes" << endl;
cout << "double_value : " <<
setprecision(numeric_limits<double>::digits10 + 1) <<
double_value << endl << endl;
cout << "long double : " << sizeof(long double) << " bytes" << endl;
cout << "long_double_value : " <<
setprecision(numeric_limits<long double>::digits10 + 1) <<
long_double_value << endl << endl;
return 0;
}

std::setprecision은 cout에서 출력하는 기본 정밀도를 조절함
std::setprecision(std::numeric_limits<데이터형식>::digits10+1);은 특정 데이터 형식이 표현할 수 있는 유효자릿수만큼 정밀도를 조절하겠다는 뜻
위 결과를 보면 데이터 형식마다 크기와 출력 자릿수가 다르다
4byte : +-1.18*10^(-38) ~ +- 3.4*10^(38), 6~9자리로, 일반적으로 7자리
8byte : +-2.23*10^(-308) ~ +-1.80*10^(308), 15~18자리로, 일반적으로 16자리
16byte: +-3.36*10^(-4932) ~ +-1.18*10^(4932), 33~36자리
'프로그래밍 > C++' 카테고리의 다른 글
C++의 변수 형식 변환 (0) | 2025.02.12 |
---|---|
L-value와 R-value?? (0) | 2025.02.12 |
C++ 변수 유효 범위 (0) | 2025.01.23 |
C++ iostream, 입출력 cin, cout, 네임스페이스 (0) | 2024.12.05 |
C++ 프로그램 빌드 과정 (0) | 2024.11.24 |