섹션 2 - 변수와 기본적인 자료

2025. 3. 12. 22:43·C, C++, MFC/따배C++

2.1 기본 자료형 소개

* 1 byte = 8 bits

Group Type names Notes on size /precision
Character types char Exactly one byte in size. At least 8 bits.
char16_t Not smaller than char. At least 16 bits.
char32_t Not smaller than char16_t. At least 32 bits.
wchar_t Can represent the largest supported character set.
Integer types (signed) signed char Same size as char. At least 8 bits.
signed short int Not smaller than char. At least 16 bits.
signed int Not smaller than short. At least 16 bits.
대부분 4 btytes
signed long int Not smaller than int. At least 32 bits.
signed long long int Not smaller than long. At least 64 bits.
Integer types (unsigned) unsigned char (same size as their signed counterparts)
unsigned short int
unsigned int
unsigned long int
unsigned long long int
Floating-point types float  
double Precision not less than float
long double Precision not less than double
Boolean type bool  
Void type void no storage
Null pointer decltype(nullptr)  

https://cplusplus.com/doc/tutorial/variables/

 

* (Signed) int는 음의 정수, 0, 양의 정수(자연수)를, unsigned int는 양의 정수와 0을 포함한다.

* Signed와 Unsigned는 저장되는 방식이 달라서 Unsigned가 특정 연산을 할 때는 더 빠르다.

 

	float fValue = 3.141592f;	// float는 끝에 f를 붙여줘야 float로 인식한다.
	double dValue = 3.141592;

	auto aValue = 3.141592;
	auto aValue2 = 3.141592f;

	cout << fValue << endl;
	cout << dValue << endl;

 

	int a(123);	// direct initialization
	int b{ 123 };	// uniform initialization
	int c = 123;	// copy initialization
    
	int a1(3.14);	// warning
	int b2{ 3.14 };	// error

* uniform initialization이 더 엄격하다.

 

2.2 정수형

00000000 00000000 00000000 00000001

int형은 4 bytes = 32 bits

1 bit에는 0과 1 두가지로 구분이 되므로 총 2^32개의 숫자를 표현할 수 있다. 

* 맨 처음 비트는 부호에 사용

	short s = 1;
	int i = 1;
	long l = 1;
	long long ll = 1;

	cout << sizeof(short) << endl;	// 2 = 2^16 가짓수
	cout << sizeof(int) << endl;	// 4 = 2^32 가짓수
	cout << sizeof(long) << endl;	// 4 = 2^32 가짓수
	cout << sizeof(long long) << endl;	// 8 = 2^64 가짓수

 

오버플로우 (overflow)

#include <iostream>
#include <cmath>
#include <limits>

using namespace std;

int main()
{
	short s = 1;	// 2 bytes = 16 bits

	cout << std::pow(2, sizeof(short) * 8 - 1) - 1 << endl;	// 32767 : 표현할 수 있는 가장 큰 숫자
	cout << std::numeric_limits<short>::max() << endl;	// 32767 : 표현할 수 있는 가장 큰 숫자
	cout << std::numeric_limits<short>::min() << endl;	// -32768 : 표현할 수 있는 가장 작은 숫자
	cout << std::numeric_limits<short>::lowest() << endl;	// -32768

	s = 32767;
	s += 1;

	cout << s << endl;	// -32768 : overflow

	s = -32768;
	s -= 1;

	cout << s << endl;	// 32767 : overflow

	return 0;
}

short가 표현할 수 있는 가장 큰 숫자는 32767이다.
그런데 32767에 1을 더하면 32768이 나오지 않고 -32768이 나온다.
표현할 수 있는 숫자를 넘어가서, 2진수로 표현할 때 가장 작은 수가 되는 것이다.
이런 것을 오버플로우라고 한다.

 

* 다른 데이터 타입에서도 오버플로우 발생 테스트 해보기 *

int, long, long long, unsigned short, unsigned int

 

cf) unsigned int에 -1을 넣으면 오버플로우가 발생한다.

	unsigned int i = -1;
	cout << i << endl;	// 4294967295

 

2.3 고정 너비 정수

어떤 플랫폼이든지 똑같은 데이터 사이즈를 사용하는 것

#include <iostream>

using namespace std;

int main()
{
	std::int16_t i(5);	// 해당 플랫폼에서 16bit = 2byte 짜리 데이터 타입으로 바꾼다.
	std::int8_t myint = 65;

	cout << myint << endl;	// A

	std::int_fast8_t fi(5);
	std::int_least64_t fl(5);

	return 0;
}

int16_t : 해당 플랫폼에서 16bit = 2byte 짜리 데이터 타입으로 바꾼다.

int8_t는 1byte이므로 char 형으로 처리가 된다. 따라서 위 예제에서 변수 myint의 값 65는 char로 처리가 되어 A를 출력하게 되는 것이다.

fast8_t : 8bit 데이터 타입 중 가장 빠른 것

least64_t : 적어도 8byte를 갖는 데이터 타입

 

2.4 무치형 (Void)

void는 함수를 선언할 때 타입이 없다는 뜻으로 사용한다. 즉, 리턴타입이 없을 때 사용한다.

void는 메모리를 차지하지 않는다.

int main()
{
	int i = 123;
	float f = 123.456f;

	void* my_void;

	my_void = (void*)&i;	// i의 주소
	my_void = (void*)&f;	// f의 주소

	return 0;
}

데이터 타입이 다르고, 데이터 타입의 사이즈가 다르더라도 주소의 데이터 사이즈는 동일하다.

따라서 void로 형변환하여 변수의 주소값을 담을 수 있다.

 

2.5 부동소수점 수

컴퓨터는 실수를 다루기 위해 부동소수점 수(Floating Point Numbers)를 이용한다.

Category Type 최소 크기 전형적인 크기
부동소수점 float 4 바이트 4 바이트
  double 8 바이트 8 바이트
  long double 8 바이트 8, 12, 16 바이트

최근에 나오는 언어들은 double을 기본으로 사용한다. 하지만 float에 비해 double은 사이즈가 2배이기 때문에, 컴퓨터의 연산 속도나 메모리에 부담이 될 수 있다. 숫자를 많이 다루는 경우에는 float를 많이 사용한다. 예로, 딥러닝 같은 경우에는 GPU 계산을 할 때 float 위주로 작업된다.

 

부동소수점의 한계때문에 사용 시 주의가 필요하다.

 

#include <iostream>
#include <iomanip>
#include <limits>

using namespace std;

int main()
{
	float f;
	double d;
	long double ld;

	cout << sizeof(f) << endl;	// 4 sizeof(float)와 동일하다.
	cout << sizeof(d) << endl;	// 8
	cout << sizeof(ld) << endl;	// 8

	cout << numeric_limits<float>::max() << endl;	// 3.40282e+38
	cout << numeric_limits<double>::max() << endl;	// 1.79769e+308
	cout << numeric_limits<long double>::max() << endl;	// 1.79769e+308

	cout << numeric_limits<float>::min() << endl;	// 1.17549e-38
	cout << numeric_limits<double>::min() << endl;	// 2.22507e-308
	cout << numeric_limits<long double>::min() << endl;	// 2.22507e-308

	cout << numeric_limits<float>::lowest() << endl;	// -3.40282e+38
	cout << numeric_limits<double>::lowest() << endl;	// -1.79769e+308
	cout << numeric_limits<long double>::lowest() << endl;	// -1.79769e+308

	return 0;
}

* min은 표현할 수 있는 가장 작은 값의 절대값을 리턴한다. 최소값을 알고 싶으면 lowest()를 이용한다.

 

	cout << 3.14 << endl;
	cout << 31.4e-1 << endl;	// 3.14 = 3.14 * 10^-1
	cout << 31.4e-2 << endl;	// 0.314 = 31.4 * 10^-2
	cout << 31.4e1 << endl;		// 314	= 31.4 * 10^1
	cout << 31.4e2 << endl;		// 3140 = 31.4 * 10^2

 

	cout << 1.0 / 3.0 << endl;	// 0.333333
	cout << setprecision(16);
	cout << 1.0 / 3.0 << endl;	// 0.3333333333333333
	
	float f(123456789.0f);	// 10 significant digits
	cout << setprecision(9);
	cout << f << endl;	// 123456792

	double d(0.1);
	cout << d << endl;	// 0.1
	cout << setprecision(17);
	cout << d << endl;	// 0.10000000000000001

	double d1(1.0);
	double d2(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1);
	cout << d1 << endl;	// 1
	cout << d2 << endl;	// 0.99999999999999989
	// 부동소수점 오차의 누적

 

#include <iostream>
#include <cmath>

using namespace std;

int main()
{
	double zero = 0.0;
	double posinf = 5.0 / zero;
	double neginf = -5.0 / zero;
	double nan = zero / zero;

	cout << posinf << endl;	// inf
	cout << neginf << endl;	// -inf
	cout << nan << endl;	// -nan(ind)

	cout << isnan(nan) << endl;	// 1
	cout << isnan(1.0) << endl;	// 0

	cout << isinf(posinf) << endl;	// 1
	cout << isinf(neginf) << endl;	// 1

	return 0;
}

 

* isnan : nan인지 확인하는 함수 (include cmath)

* isinf : inf인지 확인하는 함수 (include cmath)

 

2.6 Boolean 자료형과 조건문 if

Boolean 자료형은 조건을 판단할 때 많이 사용한다.

Boolean 자료형이 가질 수 있는 값은 true(1), false(0) 두 가지 뿐이다.

 

#include <iostream>

using namespace std;

int main()
{
	bool b1 = true;	// copy initialization
	bool b2(false);	// direct initialization
	bool b3{ true };	// uniform initialization
	b3 = false;

	cout << std::noboolalpha;
	cout << b3 << endl;	// 0
	cout << b1 << endl;	// 1

	cout << std::boolalpha;
	cout << b3 << endl;	// false
	cout << b1 << endl;	// true

	// not operator
	cout << !true << endl;	// false
	cout << !false << endl;	// true

	cout << (true && true) << endl;	// true
	cout << (true && false) << endl;	// false
	cout << (false && true) << endl;	// false
	cout << (false && false) << endl;	// false

	cout << (true || true) << endl;	// true
	cout << (true || false) << endl;	// true
	cout << (false || true) << endl;	// true
	cout << (false || false) << endl;	// false

	return 0;
}

 

2.7 문자형 char

#include <iostream>

using namespace std;

int main()
{
	char c1(65);
	char c2('A');

	cout << c1 << " " << c2 << " " << int(c1) << " " << int(c2) << endl;	// A A 65 65

	return 0;
}

* c-style casting
cout << (char)65 << endl;
cout << (int)'A' << endl;

* c++ stlye casting
cout << char(65) << endl;
cout << int('A') << endl;

* 컴파일러에 casting이 문제 없는지 확인하는 과정을 거친다.

cout << static_cast<char>(65) << endl;
cout << static_cast<int>('A') << endl;

#include <iostream>

using namespace std;

int main()
{
	char c1(65);

	cin >> c1;
	cout << c1 << " " << static_cast<int>(c1) << endl;

	cin >> c1;
	cout << c1 << " " << static_cast<int>(c1) << endl;

	return 0;
}

위 코드에서 abc를 입력하면, 처음 cin에선 c1이 char형이기 때문에 a만 처리된다. 그리고 나머지 bc는 버퍼에 저장되어 있다가 두번째 cin에서 b가 처리된다.

 

#include <iostream>

using namespace std;

int main()
{
	char c1(65);

	cout << sizeof(char) << endl;	// 1
	cout << (int)numeric_limits<char>::max() << endl;	// 127
	cout << (int)numeric_limits<char>::lowest() << endl;	// -128

	cout << sizeof(unsigned char) << endl;	// 1
	cout << (int)numeric_limits<unsigned char>::max() << endl;	// 255
	cout << (int)numeric_limits<unsigned char>::lowest() << endl;	// 0

	return 0;
}

 

\n : new line

\t : tab

 

* endl과 \n의 차이

endl은 버퍼에 있는걸 무조건 화면에 출력하고 줄을 바꾼다. 하지만 \n은 버퍼에 남아있을 수 있다.

std::flush는 버퍼에 있는걸 출력하고 줄을 바꾸지 않는다.

 

wchar_t c;
char32_t c3;

 

2.8 리터럴 상수 (Literal Constants)

	float pi = 3.14f;
	unsigned int n = 5u;
	long n2 = 5L;
	double d = 6.0e-10;

* float는 초기화 변수 끝에 f를 붙여 준다. f를 붙이지 않으면 double로 인식한다.

float pi = 3.14;

이렇게 선언하면 3.14가 double에서 float로 casting 되어 pi에 저장된다.

 

* Decimal (10진수) : 0 1 2 3 4 5 6 7 8 9 10

* Octal (8진수) : 0 1 2 3 4 5 6 7 10 11 12 13

* Hexa (16진수) : 0 1 2 3 4 5 6 7 8 9 A B C D E F 10

	int x1 = 012;	// 8진수의 표현 -> 앞에 0 붙인다.
	cout << x1 << endl;	// 10

	int x2 = 0xF;	// 16진수의 표현 -> 앞에 0x 붙인다.
	cout << x2 << endl;	// 15

	int x3 = 0b1010;	// 2진수의 표현 -> 앞에 0b 붙인다.: c++14부터 가능하다.
	cout << x3 << endl;	// 10

	int x4 = 100'000'000;	// c++14부터 숫자 사이에 입력된 '는 컴파일러가 무시한다. 수를 구분하기 위해 사용하면 유용하다.
	cout << x4 << endl;

 

* magic number 대신 const로 선언해서 사용하는게 좋다.

 

2.9 심볼릭 상수 (Symbolic constants)

	const double gravity{ 9.8 };	// gravity 값을 바꿀 수 없는 상수로 지정한다.

const는 고정된 숫자로 만들 때 사용한다.

상수는 값이 정해지면 바꿀 수 없기 때문에 반드시 초기화를 해줘야 한다.

 

#include <iostream>

using namespace std;

// 파라미터로 전달된 값은 바꿀 필요가 없으므로 const를 붙여서 선언한다.
void printNumber(const int my_number)
{
	int n = my_number;	// 만약 바꾸려면 새로운 변수에 넣어서 사용한다.
	cout << n << endl;
}

int main()
{
	printNumber(123);

	return 0;
}

 

	int number;
	cin >> number;

	const int my_const(123);
	const int special_number(number);

	// number는 바꿀 수 있지만, special_number는 못 바꾼다.

	// my_const는 컴파일 시 정해진다. (컴파일 상수)
	// special_number는 실행을 해 봐야 알 수 있다. (런타임 상수)

	constexpr int my_const2(1234);	// 컴파일 시 결정되는 상수임을 명시한다.
	constexpr int special_number2(number);	// error

 

* define는 지양한다. 적용 범위가 너무 넓어서 디버깅이 힘들기 때문에. const를 사용하기로 한다.


const가 여기저기 있으면 헷갈리기 때문에 따로 모아 놓고 사용한다.

// MY_CONSTANTS.h
namespace constants
{
	constexpr double pi(3.141592);
	constexpr float gravity(9.8);
}
#include <iostream>
#include "MY_CONSTANTS.h"

int main()
{
	double a = 2 * constants::pi;

	return 0;
}
저작자표시 비영리 변경금지 (새창열림)

'C, C++, MFC > 따배C++' 카테고리의 다른 글

섹션 1 - C++의 기초적인 사용법  (0) 2024.07.01
섹션 0 - 시작해봅시다  (0) 2024.02.13
'C, C++, MFC/따배C++' 카테고리의 다른 글
  • 섹션 1 - C++의 기초적인 사용법
  • 섹션 0 - 시작해봅시다
김고파
김고파
채워나가는 중
  • 김고파
    개발자 김고파
    김고파
  • 전체
    오늘
    어제
    • all
      • C, C++, MFC
        • 따배C++
      • Qt
      • OpenCV
      • Data Structure
      • Dev Tools
      • JAVA
  • 링크

    • github
    • 네이버블로그
    • BOJ
  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
김고파
섹션 2 - 변수와 기본적인 자료
상단으로

티스토리툴바