배움 저장소

[홍정모의 따라하며 배우는 C++] 2.변수와 기본적인 자료형 본문

Programming Language/C++

[홍정모의 따라하며 배우는 C++] 2.변수와 기본적인 자료형

시옷지읏 2021. 12. 12. 01:42

2.1 기본 자료형 소개(Fundamental Data Types)


Fundamental types

- 자료형마다 저장공간이 정해져있다. 큰 저장공간을 사용하는데 이를 활용하지 않으면 낭비이다.

- 자료형은 필요에 맞게 사용함이 좋다.

 

character 문자

-이모티콘 같이 다양한 문자를 사용함에 따라 저장공간이 많은 char 자료형이 필요했다. 2byte, 4byte char 자료형이 있음을 확인할 수 있다.

-wchar_t는 windows 개발에 여럿 쓰인다. Linux- window간 호환성 문제가 생길 수 있어 잘 사용하지 않는 추세이다.

 

Integer 정수

- signed 보다 unsigned 연산이 빠를 때가 있다. 간단한 연산을 수없이 반복할 때 unsigned을 사용하면 유리하다.

- Italic 표시된 keyword는 생략할 수 있다

- char 자료형은 정수, 문자 모두 표기할 수 있다. 단 std::cout은 char 자료형을 문자로 취급한다.

 

float 실수

- float를 single precision, double을 double precision이라 부른다.

 

literal 실수 값을 입력할 때 float와 double은 어떻게 구분할까?

- float 값은 double과 구분하기위해 끝에 f를 붙여준다. f를 붙여주지 않으면 double 자료형으로 인식해 trancation이 발생한다(저장공간이 큰 자료형에서 저장공간이 좁은 자료형으로 데이터를 복사하여 데이터 손실이 일어남)

- 아래 코드에서 출력값이 반올림 되는 이유는 exponent * mantissa로 계산할 수 있는 값이 3.141592의 근사치이기 때문이다. 가까운 값을 할당해준다.

double d = 3.141592;
float f = 3.141592f; // float value needs 'f' at the end

cout << d << endl; // >> 3.14159
cout << f << endl; // >> 3.14159

 

void

- void type은 저장공간을 차지하지 않는다

- 함수의 매개변수가 없거나 반환값이 없을 때 사용한다

 

자료형이 메모리를 사용하고 있는 모습

- 8bit = 1byte

- char 자료형은 1byte를 사용하고 있다. int 자료형은 4byte를 사용하고 있다.

 

변수의 다양한 초기화 방법

- 이 때 입력값과 자료형이 일치하지 않으면 데이터 손실이 일어난다

int a = 1; // copy inialization
int b(2);  // direct inialization
int c{ 3 };  // uniform inialziation

int A = 1.1;   // Warning, conversion from double to int
int B(2.2);    // Warning, conversion from double to int
int C{ 3.3 };  // Error!!! conversion from double to int

 

copy initialization과 direct initialization은 다른 자료형을 할당하면 자료형 변환(casting)을 해준다

uniform initalization은 자료형이 맞지 않으면 에러메시지를 출력한다

- 예제에서 double(8byte) 데이터를 int(4byte)로 변환하므로 데이터 손실이 나타난다.

int A = (int)1.1;
int B((int)2.2);

 

 

같은 자료형의 변수를 여럿 초기화 할 수 있다

	int x = 2, y = 3, z = 4;
	int X = 2, Y(3), Z{ 4 }; // Not recommend so messy.

 

2.2 정수형 (Integers)


Category Type 최소크기 기타
Character(문자) char 1 byte 네트워크에서 분야에서 최소크기로 활발하게 사용
Integer(정수) short 2 byte  
  Int 2 byte 최소크기로 지정되어있으나 대부분 4byte
  long 4 byte  
  long long 8 byte C99/C++11 type

 

자료형의 최대값 최소값을 확인하는 standard library

- numeric_limits<type>::function( )을 활용하여 해당 자료형 정보를 확인해볼 수 있다.

#include <iostream>
#include <cmath>     // pow( )
#include <limits>    // numeric_limits
int main() {
	using namespace std;

	short s = 1;
	cout << pow(2, sizeof(signed short) * 8 - 1) - 1 << endl; 
	//                                             ^    ^ 
	//                       15bit( 1bit is for +/- )   Start from 0
	
	cout << numeric_limits<short>::max() << endl;
	cout << numeric_limits<short>::min() << endl;  // float's min and lowest is diff
	cout << numeric_limits<short>::lowest() << endl;

	cout << SHRT_MAX << endl;
}

 

float 자료형의 min 값과 lowest 값은 다르다.

- numeric_limits에서 min( ) 값은 가장 작은 절대값을 반환한다. 음수 최소값은 lowest( )이 반환한다

cout << numeric_limits<float>::max() << endl;    //>> 3.40282e+38
cout << numeric_limits<float>::min() << endl;	 //>> 1.17549e-38
cout << numeric_limits<float>::lowest() << endl; //>> - 3.40282e+38

 

정수 나누기 정수 결과값의 자료형은?

- 정수 / 정수 값은 정수 결과값이 나온다

- 서로 다른 자료형의 연산은 자료형을 일치시킨 다음 연산을 수행한다. 이 때 더 큰 자료형으로 일치시킨다.

cout << 22 / 4 << endl;         // >> 5
cout << float(22) / 4 << endl;  // >> 4.4

 

2.3 C++ 11 고정너비정수 (Fixed-width Integers)


컴파일러러 마다 자료형의 저장공간 크기가 다를 수 있다

- c++표준 Fundamental types는 각 자료형이 가져야할 최소한의 저장공간을 정의하였다. 제작자는 이를 따라 컴파일러를 제작한다.

- <cstdin>라이브러리에서 지원하는 자료형은 표준으로 정해져 있다.

- <cstdint> 내부에 정의된 자료형을 사용하여 multiplatform에서 실행가능한 프로그램을 만들 수 있다.

#include <iostream>
//#include <cstdint> // Fixed-width Integers
                     // iostream already including this

int main() {

	std::int16_t i_two_byte(5);
	std::int8_t i_one_byte(65); // this print out 'A' char

	std::int_fast8_t i_one_byte_fastest(5);
	std::int_least64_t i_least_eight_byte(5);
}

 

2.4 무치형 (보이드, Void)


- void 자료형을 사용하여 포인터 값을 저장할 수 있다. void 포인터는 dereference/indirect는 할 수 없다. 해당 자료형을 알고 있어야 해당 값을 어떻게 해석할지 알 수 있기 때문이다.

	void variable_void; // Error! void doesn't take any memory

	int i = 123;
	float f = 123.12345f;

	void* ptr;

	ptr = (void*)&i; // possible
	ptr = (void*)&f; // possible

 

2.5 부동소수점수 floating point numbers


Type 최소크기 자주 차용되는 크기
float 4 byte 4 byte
double 8 byte 8 byte
long double 8 byte 8, 12, 16 byte

 

Floating Point Numbers가 이진수로 표현되는 원리

- 이 때 지수부분에서 2^(7-127)을 보자. -127은 bias이다. 메모리에 저장되고 계산되는 규칙이 있다.

 

Scientific notation 'E'

- 큰 수를 다루는 과학에서 숫자를 쉽게 표기하기위하여 10의 지수를 E+1 형태로 사용한다.

cout << 3.14 << endl;	 // >> 3.14
cout << 31.4E-1 << endl; // >> 3.14
cout << 314E-2 << endl;  // >> 3.14

 

<iomanip> Input output manipulator

- 입출력을 제어할 수 있는 라이브러리로, double 자료형의 precision을 더 자세하게 출력할 수 있다.

#include <iostream>
#include <iomanip> // input/output manipulator

int main() {

	std::cout << 1.0 / 3.0 << std::endl; // >> 0.333333

	std::cout << std::setprecision(16);// default is 6

	std::cout << 1.0 / 3.0 << std::endl; // >> 0.3333333333333333
	 
}

 

부동소수점 수는 지수+가수 형태로 숫자를 표현한다

- 표현할 수 있는 수가 정해져 있다. 따라서 입력값과 가장 가까운 수를 저장한다.

- setprecision으로 정확도를 정하면 해당 정확도 내에서 가장 가까운 수를 저장한다.

	float f(123456789.0f); // 10 significant digits
	cout << std::setprecision(9); // float give closest number
	cout << f << endl;     // >> 123456792
	
	cout << std::setprecision(5); 
	cout << f << endl;     // >> 1.2346e+08

 

부동소수점 수가 만드는 오차

	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 << std::setprecision(17);
	cout << d1 << endl; // >> 1
	cout << d2 << endl; // >> 0.99999999999999989
	                    //    bias are accumulating

 

double 자료형이 만들어내는 오류값

- double 자료형은 infinite와 nan 값을 출력할 수 있다.

- <cmath> library에 있는 함수를 사용하여 double 자료형에 저장된 값이 오류값을 확인가능하다.

#include <iostream>
#include <cmath> // isinf, isnan
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)
	                        //    indeterminate

    // How to prevent to get above example? 
    // use <cmath> library's function
    cout << isinf<double>(posinf) << endl; // >> 1
    cout << isinf<double>(neginf) << endl; // >> 1
    cout << isnan<double>(nan) << endl;	   // >> 1
    cout << isnan<double>(1.2) << endl;	   // >> 0
}

 

2.6 불리언 자료형과 조건문 if


Bool 자료형

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

	//cout << std::noboolalpha; // set bool value's output is num
	cout << std::boolalpha;    // set bool value's output is string

	cout << ! b1 << " " << b2 << " " << b3 << endl; // >> false true true

 

if 조건문

- if( expression )에서 expression 값이 0이면 false, 0이 아니면 true이다. 따라서 0이 아닌 어떤 값을 넣어도 true이다.

if(5)
{
    // do sth..
}

 

2.7 문자형 char type


정수<->문자 형변환이 가능하다

char c1(65);  // assign number but printing character
char c2('A');
cout << c1 << " " << c2 << endl;            // >> A  A

// C style casting 
cout << (int)c1 << " " << (int)c2 << endl;  // >> 65 65

// C++ style
cout << int(c1) << " " << int(c2) << endl;  // >> 65 65

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

 

std::endl VS '\n'

- 입력/출력 값이 어마어마하게 클 때 '\n'문자가 버퍼에 남아 출력되지 않는 경우가 생긴다. 이때 std::endl이 유용하다.

     ' \n ' : 단순히 줄바꿈 문자를 출력한다.

 std::endl : std::cout에서 사용하는 buffer에 있는 값을 모두 출력시킨다. 이후 줄바꿈 문자를 출력한다.

참고) std::flush를 사용하면 buffer에 있는 값을 모두 출력시킨다. 줄바꿈 문자는 없다.

 

2.8 리터럴 상수 literal constants


quatation mark( ' )를 사용하면 숫자를 읽기 쉽게 표기할 수 있다. Compiler는 이를 무시한다.

/* suffix of literal number */
unsigned int ui = 5u;
long li = 5'000'000L; // ' is neglected by compiler
double d = 1234.5678E-4; 

/* Binary */ 
int binary = 0b0000'0101; // 1 + 4 = 5

/* Octal */ 
int oct = 012;       // 8 + 2 = 10

/* Hex */ 
int hex = 0x12;      // 16 + 2 = 18

 

2.9 심볼릭 상수 symbolic constants


Symbolic constant: Identifier(식별자) 또는 이름을 가진 고정 값이다. const keyword를 사용한다.

                          함수의 Parameter(매개변수)에 자주 사용한다.

 

compile time constant와 runtime constant

- 상수는 compile time 혹은 run time에 결정되어야 한다. C와 다르게 run time 상수를 허용한다

	const int compile_time_constant(100);

	int number;
	cin >> number;

	const int runtime_constant(number);

 

constexpr Keyword in C++17

- constant 상수가 compile time에 초기화 되었는지 확인하는 keyword이다.

- constexpr keyword가 붙은 변수가 runtime에 초기화되면 Error를 발생시킨다.

	constexpr int only_compile_constant(-100);
	// ^ this check whether inited at compile time
	constexpr int error_runtime_constant(number); // Error!

 

C style Macro는 C++에서 쓰지 않는다. constant를 사용하자

- #define Macro는 저장공간을 차지하지 않아 디버깅이 힘들다.

- Scope가 너무 넓다. File Scope라 사용하지 않는 곳에서도 존재한다.

 

const 변수는 header 파일 내 namespace에서 묶어놓으면 쓰기쉽다

- 상수 값을 변경할 때 편리하다. header -> namespace에서 해당 상수 값을 바꾸면 모든 파일에 적용된다.

// constants.h
namespace constants
{
  constexpr double pi(3.141592);
  constexpr double gravity(9.8);
}

// main.cpp
#include <iostream>
#include "constants.h"

int main()
{
  double radius;
  std::cin >> radius;
  double circle = radius * radius * constants::pi; 
}
Comments