본문 바로가기

Programming/C++ 2

[C++] 3장-4. C++ 산술 연산자

반응형

데이터형 변환

11가지 정수형

3가지 부동 소수점형

 

데이터형을 혼합해 사용하면

데이터형의 불일치를 해결을 위해 데이터형 변환

  • 특정 데이터형 변수에 다른 데이터형의 값을 대입
  • 수식에 데이터형을 혼합해 사용
  • 함수에 매개변수를 전달

대입 구문에서의 데이터형 변환

so_long이 long형이고 thirty가 short형일때

so_long=thirty; // long형 변수에 short형 값을 대입

 

thirty의 short형 (16비트 값)을 long형 값(32비트 값)으로 확장해 새로운 값을 대입

 

데이터형 변환 문제점
double -> float : 큰 부동 소수점을 작은 부동 소수점 유효 숫자의 손실 / 범위를 벗어날 경우 예측 불가
부동 소수점형을 정수형으로 소수부 손실 / 범위를 벗어날 경우 예측 불가
 long -> short : 큰 정수형을 작은 정수형 범위를 벗어날 경우 하위 바이트들만 복사

부동 소수점수를 정수형에 대입할 때의 문제점

  • 소수부 버림
  • float형 값이 너무 클 경우 int형 변수에 온전히 대입 불가 [예측 불가]
#include <iostream>
using namespace std;

int main()
{
	cout.setf(ios_base::fixed, ios_base::floatfield);
	float tree = 3;
	int guess = 3.9832;
	int debt = 7.2E12;
	cout << "tree= " << tree << endl;
	cout << "guess= " << guess << endl;
	cout << "debt= " << debt << endl;
	return 0;
}

 

tree가 부동 소수점형 값인 3.0으로 대입

int형 변수 guess에 3.9832를 대입하면

정수부 3만 대입하고 소수부를 버린다.

 

int형 변수 debt에는 7.2E12라는 큰 값 저장 불가

-> 1634811904 [약 1.6E09]

 


{}를 사용할 경우의 초기화 변환

변환된 변수가 완벽하게 값을 유지할 수 있다면, 정수형을 다른 정수형이나 부동 소수점형으로 변환할 때 narrawing 허용

-> long 변수를 int 값으로 초기화 가능

 

const int code=66;
int x=66;
char c1{31325}; //narrowing, 허용 안됨
char c2={66}; //char가 66을 유지할 수 있기 때문에 허용
char c3 {code}; //상수형 int 변수 code가 66이기 때문에 허용
char c4={x}; //x가 상수가 아니기 때문에 허용 안됨

x=31325;
char c5 = x; //초기화에 의해 허용됨

수식에서의 데이터형 변환 [여러가지 데이터형을 혼합하여 사용할 때]

1. 자동데이터형 변환: 어떤 데이터형은 자동으로 데이터형이 변환

2. 어떤 데이터형은 수식에서 다른 데이터형과 혼합하여 사용되었을 때 데이터형이 변환

 

1. 자동데이터형 변환

 

정수승급 : bool, char, unsigned char, signed char, short 형 값은 모두 int형으로 변환된다.

short chickens= 20; //첫 번째 행
short ducks = 35; //두 번째 행
short fowl = chickens + ducks; //세 번째 행

-> 세 번째 행 실행시 chickens와 ducks의 값을 int형으로 각각 변환 후 더하고 short형으로 다시 변환해 변수 fowl 대입

[가장 빠르게 처리되는 데이터형은 int형이기 때문에]

 

  • 정수 승급의 예
    • short형이 int형보다 크기가 작을 경우 unsigned short형이 int형으로 변환
    • short형이 int형과 크기가 같은 경우에는 unsigned short형이 unsigned int형으로 변환
      -> unsigned short형이 승급될 때 데이터 손실이 일어나지 않도록
    • wchar_t형은 int, unsigned int, long, unsigned long형 중 충분히 큰 첫 번째 데이터형으로 승급

2. 서로 다른 데이터형을 혼합하여 사용할 때

:작은 크기의 데이터형이 큰 크기의 데이터형으로 변환

 

컴파일러가 검사를 진행하는 순서

  1. 한쪽 피연산자가 long double형이면 상대편 피연산자를 long double형으로 변환
  2. 한쪽 피연산자가 double형이면, 상대편 피연산자를 double형으로 변환
  3. 한쪽 피연산자가 float형이면, 상대편 피연산자를 float형으로 변환
  4. 피연산자들이 정수형이므로 정수 승급
  5. 양쪽 피연산자가 모두 signed이거나 모두 unsgined일 경우에 두 피연산자의 상대적 크기에 따라 큰 쪽으로 변환
  6. 한쪽 피연산자가 signed 이고 다른 쪽이 unsgined일 경우, unsgined 피연산자가 signed 피연산자보다 상대적으로 크다면 unsigned 피연산자의 형으로 변환
  7. signed 형이 unsigned형의 모든 값을 표현할 수 있다면, unsigned 피연산자가 signed형으로 변환
  8. 5,6,7에 해당하지 않은 경우 양쪽 피연산자 모두 signed형의 unsgined 버전으로 변환

정수형 타입의 순위

signed 형 : long long, long, int, short, signed char

 

[char, signed char, unsigned char는 모두 같은 순위로 본다]

[bool형은 가장 낮은 순위]

[wchar_t, char16_t, char32_t는 원형과 같은 순위]

 


매개변수를 전달할 때의 형 변환

:C++의 함수원형이 제어

 

함수원형이 매개변수를 제어하는 것을 막을 경우엔 char형과 chosrt형 (signed/unsigned) 정수 승급 수행

C와의 호환성을 위해 float형 매개변수를 double형으로 변환하여 전달


데이터형 변환자

:강제로 데이터형의 변환

 

thron변수에 저장된 int형 값을 long형으로 강제 변환

(long) thorn //thorn의 long형 변환을 리턴

long (thorn) //thorn의 long형 변환을 리턴

 

->데이터형 변환자는 thorn 변수 자체는 변경하지 않고 새로운 값을 만든다.

 

cout<< int('Q'); //'Q'에 해당하는 정수 코드를 디스플레이한다.

 

즉, 일반화하면

(typename) value //value를 typeNmae형으로 강제로 변환한다.

typename (value) //value를 typeName형으로 강제로 변환한다.

 

1. C에서 사용하는 방법

2. C++에서 사용하는 방법이며 함수 호출과 비슷하게 표현

->사용자 정의 클래스를 위해 설계하는 데이터형 변환

 

[제한적인 4개의 데이터형 변환 연산자 도입 -> 15장에서]

 

 

static_cast<>연산자는 어떤 수치 데이터형을 다른 수치 데이터형으로 변환하는 데 사용

 

static_cast<typeName> (value) //value를 typeName형으로 변환

 

일반화

static_cast<typeName> (value) //value를 typeName형으로 변환

 

조류와 동물들의 정수형 개체 수를 구하는 프로그램

auks에 대한 계산 : 두 개의 부동 소수점수를 더하고 그 합을 int형으로 변환해 auks로 대입

 

[bats와 coots에 대한 계산은

데이터형 변환자를 사용해 두 개의 부동 소수점수를 int형으로 변환한 후 더해 bats와 coots에 대입]

 

[데이터형 변환자를 사용해 char형 값을 그에 해당하는 ASCII 코드로 출력하는 방법]

 

#include <iostream>
using namespace std;

int main()
{
	int auks, bats, coots;

	// 다음 구문은 두 값을 double형으로 더한 후에
	// 그 합을 int형으로 변환하여 대입한다
	auks = 19.99 + 11.99;

	// 다음 두 구문은 두 값을 int형으로 변환한 후에 더한다
	bats = (int)19.99 + (int)11.99; //C 스타일
	coots = int(19.99) + int(11.99); //C++ 스타일

	cout << "바다오리 = " << auks << ", 박쥐 = " << bats;
	cout << ", 겸둥오리 = " << coots << endl;

	char ch = 'Z';
	cout << "코드 " << ch << " 의 값은 "; //char형으로 출력
	cout << int(ch) << endl; //int형으로 출력
	cout << "코드 Z의 값은 ";
	cout << static_cast<int>(ch) << endl; //int형으로 출력
	
	return 0;
}

 

-> auks : 19.99와 11.99=31.98, 소수부가 버려지고 31만 대입

-> 데이터형 변환자를 사용하면 덧셈이 수행하기 전에 소수부가 버려져

-> 19 + 11 = 30이 bats와 coots에 대입된다.

-> 마지막의 cout 구문은 데이터형 변환자를 사용해 char형 값을 int형으로 변환하여 출력

-> 이 구문은 'Z'에 해당하는 값을 문자가 아닌 정수로 출력

 

이 프로그램에서 데이터형 변환자를 사용하는 이유

1. double형으로 저장하지만 int형으로 계산해야 하는 값들에 데이터형 변환자가 사용

[부동 소수점수들을 정수값으로 모델링해야 하는 계산]

 

2. 특정 목적에 맞게 강제로 데이터형을 변환한다.

char형 변수 ch에는 문자 Z에 대한 코드가 들어 있지만

ch를 int형으로 강제로 데이터형을 변환하고 cout 구문을 사용하면  ch에 저장한 ASCII코드를 출력


C++11에서의 auto 선언

9장에서의 auto

 

초기화 선언시 데이터형을 쓰지 않고 auto를 사용할 수 있다.

auto n =100; //n은 int
auto x =1.5; //x은 double
auto y =1.3e12L; //y는 long double

-> 데이터형을 추론하는 것에 문제가 있을 수 있다.

auto x=0.0; //0.0이 double이기 때문에 문제가 없음
double y=0; //0이 자동으로 0.0으로 변환되기 때문에 문제가 없음
auto z=0;   //0이 int이기 때문에, z가 int가 되어 문제가 생김

-> 자동 형변환의 경우에는 문제가 발생

-> 자동으로 변수형을 추론하는 건 STL같은 변수형을 다룰 때 유용하다.

 

std :: vector<double> scores;
std :: vector<double> :: iterator pv = scores.begin();
std :: vector<double> scores;
auto pv = scroes.begin();

 

반응형