삶의 공유

[C++] C++와 표준 라이브러리 초단기 속성코스(연산자, 타입, 구조체) 본문

Programing/C++

[C++] C++와 표준 라이브러리 초단기 속성코스(연산자, 타입, 구조체)

dkrehd 2021. 1. 28. 21:41
728x90
반응형

출저 : 책, 전문가를 위한 C++

변수이 값을 변경 할수 없다면 변수를 사용할 이유가 없다. 다음 표는 C++에서 변수값 변경 용도로 가장 흔히 사용되는 연산자와 사용예를 보여주고 있다.

C++연산자는 이항(바이너리) 연산자, 단항(유너리) 연산자, 삼항(터너리) 연산자로 분류 할 수 있다.

 

출저 : 책, 전문가를 위한 C++

 

 

 

다음 코드는 가장 자주 사용 되는 변수 타입과 연산자를 사용하는 예를 보여주고 있다.

#include <iostream>
using namespace std;

int main()
{
    int someInteger = 256;
    short someShort;
    long someLong;
    float someFloat;
    double someDouble;

    someInteger++; // 257
    someInteger *= 2; // 514
    someShort = static_cast<short>(someInteger); // 514 
    someLong = someShort * 10000; // 5140000
    someFloat = someLong + 0.785f; //5.14e+06
    someDouble = static_cast<double>(someFloat) / 100000; // 51.4
    cout << someDouble << endl;
}

 

C++컴파일러는 일정한 순서에 따라 표현식을 평가한다. 여러가지 연산자가 복잡하게 뒤엉켜 있다면 코드만 실행순서를 가늠하기 힘들다.

이럴때는 복잡한 표현식을 작은 표현식 여러개로 나눠서 작성하거나 소괄호를 이용하여 표현식을 작은 단위로 묶어서 표현하는 것이 좋다.

 

int i = 34 + 8 * 2 + 21 / 7 % 2;
int i = 34 + (8 * 2) + ((21 / 7) % 2);

 

코드를 실행해보면 두 표현식 모두 i값이 51로 같은 결과를 낸다는 것을 알 수 있다.

C++에서는 /, *, %연산을 먼저 수행하고, 그담으로 덧샘과 뺼셈을 계산하고, 마지막으로 비트 연산을 수행한다. (우선순위가 같을 경우는 왼쪽에서 오른쪽 순서로 계사한다.) 표현식에 소괄호를 넣어주면 컴파일러에 평가 순서를 명확히 알려줄수 있다.

 

 

타입

 

C++에서는 기본 타입(int, bool등)을 조합해서 좀 더 복잡한 타입을 정의 할 수 있다. 이 절에서 소개하는 기법은 C언어에서도 사용하던 것으로, C++에 어느정도 익숙해지면 사용할 일이 거의 없으나, 다른 사람이 작성한 코드를 이해하려면 이런 방식을 아랑두는 것도 좋다.

 

정수는 사실 연속적으로 나열한 숫자중 하나를 표현한 것이다.

열거 타입(enum)을 사용하면 숫자를 나열하는 방식과 범위를 마음대로 정의해서 변수를 선언하는데 활용 할 수 있다. 

 

예를 들어 체스 프로그램을 작성할 때 각 말의 종류를 다음과 같이 int타입의 상수로 표현한다고 하자.

 

이때 말의 종류를 나타내는 정수 타입의 변수 앞에 const란 키워드를 붙이면 그 값이 변하지 않게 만들 수 있다.

const int PieceTypeKing = 0;
const int PieceTypeQuuen = 1;
const int PieceTypeRook = 2;
const int PieceTypePawn = 3;

// 기타
int myPiece = PieceTypeKing;

이렇게 표현해도 되지만 자칫 위험한 상황이 발생할 수 있다. 말을 표현하는 myPiece를 일반 int값으로 표현했기 때문에 다른 프로그래머가 myPiece값을 증가시키는 코드를 작성할 수도 있다. 

킹을 나타내는 값에 1을 더하면 퀸이 돼버리는데, 그러면 체스게임이 망가진다.

 

이때 enum타입을 적용하면 변수에 지정할수 있는 값의 범위를 엄격하게 제한하기 때문에 이러한 문제를 방지할 수 있다.

다음과 같이 PieceType이라는 enum타입을 새로 정의한다.

enum PiceType { PieceTypeKing, PieceTypeQueen, PieceTypeRook, PieceTypePawn };

enum 타입을 구성하는 멤버는 내부적으로 정숫 값으로 표현된다. PieceTypeKing에 실제로 할당된 값은 0이다.

 

아니면 PieceType변수에 대해 사칙연산 or 일반 정숫값 처럼 다루는 코드를 작성하면 컴파일 경로 또는 에러메세지를 발생한다.

enum 타입을 정의 할때, 각 멤버에 해당하는 정숫값을 직정 지정할 수도 있다.

 

enum PiceType { PieceTypeKing = 1 , PieceTypeQueen, PieceTypeRook = 10, PieceTypePawn };

여기서 PieceTypeQueen은 컴파일러에 의해 2라는 값이 대입되고, PieceTypePawn은 컴파일러에 의해 11이라는 값이 자동으로 대입된다.

 

스토롱 타입 : 타입을 엄격히 따지는 것.

 

타입을 엄격하게 적용하고 싶다면 enum class를 사용한다. 예를 들어 앞에서 enum으로 선언한 PieceType을 다음과 같이 타입 세이프버전으로 정의할 수 있다.

 

enum class PieceType
{
	King = 1,
    Quuen,
    Rook = 10,
    Pawn
};

enum class로 정의한 열거 타입 값들의 이름은 스코프(유효 범위)가 자동으로 확장되지 않는다. 다시말해 enum class 스코프 안에서만 유효하다. 따라서, 열거 타입 값을 사용할 때마다 다음과 같이 스코프 지정 연산자를 붙여야한다.

PieceType piece = PieceType::King;

 

또한 enum class로 정의한 열거 타입 값은 자동으로 정수 타입으로 변환되지 않는다. 그래서 다음과 같이 표현 할 수 없다.

if(PieceType::Queen == 2) { ... }

 

기본적으로 열거 타입의 값은 정수 타입으로 저정된다. 하지만 다음과 같이 내부 표현 타입을 바꿀수 있다.

enum class PieceType : unsigned long
{
	King = 1,
    Quuen,
    Rook 10,
    Pawn
}

 

※ 열거타입을 사용할 때는 타입에 안전하지 않은 즉, 타입 언세이프한 enum보다는 스토롱 타입 버전인 enum class로 작성하는 것이 좋다.

 

구조체를 사용하면 기존에 정의된 타입을 한 개 이상 묶어서 새로운 타입으로 정의할 수 있다.

구체적인 대표적인 예로 데이터베이스 레코드가 있다.

직원 정보 관리 시스템을 구축하려면 각 직원의 성, 이름 직원번호 급여 정보등을 저장해야 한다. 

이 모든 정보는 emplyeestruct.h란 헤더 파일에 다음과 같이 구조체를 정의하는 방식으로 표현할 수 있다.

 

간단한 예를 들면,

emplyeestruct.h를 정의한 후,

struct Employee
{
	char firstInitial;
	char lastInitial;

	int employeeNumber;
	int salary;
};

Employee 타입으로 선언한 변수는 이 구조체에 있는 모든 필드를 가진다. 구조체를 구성하는 각 필드는 도트(.) 연산자로 접근한다.

다음 코드는 그 직원에 대한 레코드를 생성한 뒤 그 결과를 화면에 출력하는 예를 보여준다.


#include <iostream>
#include <employeestruct.h"

int main()
{
	Employee anEmployee;
	anEmployee.firstInitial = 'M';
	anEmployee.lastInitial = 'G';
	anEmployee.employeeNumber = 42;
	anEmployee.salary = 80000;

	// 직원 레코드에 저장 된 값 출력하기
	std::cout << "Employee : " << anEmployee.firstInitial << anEmployee.lastInitial << std::endl;
}

 

 

반응형