[따배씨++]Chapter2. C++ 기본 자료형
카테고리: Cpp
태그: Programming
인프런에 있는 홍정모님의 홍정모의 따라하며 배우는 C++ 강의를 듣고 정리한 내용입니다.
중간에 등장하는 ppt 내용들은 강의자료를 캡처한 것입니다.
🚆 Fundamental Data Types - C++ 기본 자료형
- C++ 표준은 최소 사이즈를 기준으로 함 (실제 사이즈는 컴파일러마다 다를 수 있음)
- signed 가 기본값. unsigned 는 표기해줘야 함
초기화 방법
int i = 123; // copy initialization
int a(123); // direct initialization
int b{123}; // uniform initialization
- direct, uniform initialization은 객체지향에서 많이 쓰임 (객체지향은 프로그래머가 데이터 타입을 만들어서 쓰는 것)
int i = 3.1415; // warning & 데이터 자르고 컴파일
int a(3.1415); // warning & 데이터 자르고 컴파일
int b{3.1415}; // 컴파일 에러
- uniform initialization이 가장 엄격함
🚆 char - 문자형
- 1 byte
- 내부적으로는 아스키 코드에 따른 정수값
- 1 byte 정수형처럼 사용하는 경우도 많음
- char16_t (2 byte), char32_t (4 byte) : 다양한 종류의 언어나 이모티콘 등을 지원하기 위해 사용
- 문자열은 string type을 사용 자주 사용해서 기본 데이터 타입 같지만 외부 라이브러리(standard)에 정의된 타입.
Q. int로 캐스팅하면 사이즈도 바뀌나? ➡️ 바뀜
char c = 'A';
cout << sizeof(c) << endl; // 1
cout << sizeof(int(c)) << endl; // 4
입출력 버퍼
우리가 문자열을 입력하고 출력할 때 한 글자 단위로 실행되지는 않는다. ‘버퍼’ 라는 임시 저장소에 저장됐다가 한꺼번에 처리된다. std::cout은 줄 바꿈을 의미하는 \n을 만나면 버퍼의 내용을 출력해버린다. 이때 문제는 출력 이후에도 버퍼가 채워질 수 있다는 것이다.
endl vs \n
- \n : 줄 바꿈
- flush : 버퍼에 있는 내용 출력 (버퍼 비우기)
- endl = flush + \n
- endl이 \n보다 조금 더 느리다고 함
🚆 int - 정수형
short i = 0; //2 byte
int i = 0; // 4 byte
long i = 0; // 4 byte - 컴파일러에 따라 다르지만, 최소 사이즈 >= int 는 보장
long long i = 0; // 8 byte
- 정수끼리의 연산은 정수 ➡️ ex) 22/5 = 4
- 피연산자 타입 다르면 큰 타입으로 저장 ➡️ 22/10 = 2.2
- 고정너비 정수: 컴파일러에 상관 없이 사이즈 고정 ➡️ int16_t (16 bit)
Overflow
cout << std::numeric_limits<int>::max() + 1<< endl; // -2147483648
cout << std::numeric_limits<unsigned int>::max() + 1<< endl; // 0
- 데이터는 범위 제한이 있고, 넘어가면 문제가 생기는데 컴파일러는 warning, error 안 해줌
signed vs unsigned
cout << std::numeric_limits<int>::max() << endl; // 2147483647
cout << std::numeric_limits<unsigned int>::max() << endl; // 4294967295
- unsigned는 음수 표기 필요 없으므로 범위가 훨씬 큼 (X2)
- 게임 역사에서 unsigned int로 인해 생긴 치명적인 버그가 많다고 함
- ex) ‘문명’ 게임에서 간디가 핵무기 써버림
- 3 - 5 ➡️ overflow
Q. signed에 unsigned 대입하면? ➡️ 그냥 signed
int a = 0;
unsigned int b = 0b1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111'1111;
a = b;
cout << a << endl; // -1
cout << b << endl; // 4294967295
음수 표기법 - Two’s complement (보수)
- Two’s complement: 0️⃣ 🔄 1️⃣
- 첫 번째 비트는 부호 의미
- 0 = -0
🚆 void
void i; // error
void *void_pointer; // ok
void function1(){};
- 메모리를 차지하지 않는 데이터
- 반환 값이 없는 함수의 리턴 타입으로 자주 쓰임
- 변수 선언 못함
- 포인터에서 요긴하게 쓰임
🚆 floating point numbers - 부동소수점 수
- 32 bit = 1bit(sign) + 8bit(exponent) + 23bit(fraction)
- exponent 부분 -127은 unsigned에서 음수 표현하기 위해
- 장점 : 단순 2진수에 비해 표현할 수 있는 범위가 매우매우X1000 커짐
- 단점 : 유효숫자(정밀도)가 비교적 떨어짐
double
float f = 3.14; // warning!
float f = 3.14f; // ok
- sizeof(double) = 2 * sizeof(float)
- c++에서 실수는 double로 인식
- float = 3.14 ⬅️ warning : double을 float으로 casting 했으니 데이터 짤릴 수도 있다!
- float = 3.14f ⬅️ 응 나 알고있어 : warning X
🚆 Boolean
- true = 1 & false = 0
- if( condition ){~}
- codition 조건문이 true이면 실행
- 사실 0 아니면 전부 실행
🚆 Literal Constatns
int x = 12; // Decimal 12 = 12
int x = 012; // Octal 12 = 10
int x = 0x12; // Hexa 12 = 18
int y = 0b1111'0011'1100'0000; // binary
- 메모리 안에 들어가는 값
- 앞에 0붙이면 8진수 (모르고 앞에 0 붙이면 큰일 남)
- 앞에 0x붙이면 16진수
- 앞에 0b붙이면 2진수 (‘는 빼고 읽음)
- 1111’0011’1100’0000 (binary) = F3C0 (hexa) ⬅️ 생각보다 자주 씀
🚆 Symbolic Constatns
Avoid magic numbers, use symbolic constants instead
중요한 숫자는 symbolic하게 갖고 다녀라!
const double gravity = 9.8;
void function1(const int my_number){};
int number;
cin >> number;
const int my_const = number; // runtime
constexpr int my_const = 123; // compile time
- const : 변경할 수 없는 상수
- 초기화 필수
- 함수에 들어가는 변수들에 많이 씀
- constexpr : compile time 에 결정
🚆 기타 자료형
auto i = 123;
int_fast16_t i = 0;
int_least16_t i = 0;
- auto : 컴파일러가 알아서 정해줌
- int_fast16_t : 16bit 이상 중 해당 컴파일러에서 가장 연산이 빠른 데이터 타입
- 플랫폼에 따라 64bit일 수도 있다.
- 캐시 문제가 생겨 오히려 느려질 수도 있다고 함…
- int_least16_t : 16bit 보다 큰 타입 중 가장 작은 데이터 타입
댓글 남기기