클라이언트/ 서버/ 엔지니어 " 게임 개발자"를 향한 매일의 공부일지

데이터 처리 1 : 간단한 변수와 const 제한자 본문

프로그래밍 언어/C++

데이터 처리 1 : 간단한 변수와 const 제한자

huenuri 2024. 8. 25. 11:07

3장에서는 데이터를 처리하는 여러가지 자료형을 배우게 된다. C 언어에서 모두 공부했던 내용이지만 C++에서는 추가된 부분도 있으니 한번 더 정리한다 생각하고 학습을 진행해본다.
2장보다는 분량이 조금 많지만 이 chapter도 3시간 안에 끝마치는 것이 목표이다.

객체 지향 프로그래밍의 진수는 사용자가 데이터형을 스스로 설계하고 확장할 수 있다는 데 있다. 사용자 자신의 데이터형을 설계한다는 것은 표현하고자 하는 데이터에 가장 적합한 형태로 사용자가 데이터형을 직접 설계할 수 있다는 것을 뜻한다.


이를 위해서는 C++에 내장되어 있는 여러 데이터형을 알고 이해해야 한다. C++에 내장된 데이터형에는 기본형과 복합형이 있다. 우선 기본형에 대해서 학습해볼 것이다.

기본형에는 정수를 표현하는 정수형과 소수부가 있는 수를 표현하는 부동 소수점형이 있다.


 

 

1. 간단한 변수

컴퓨터에 정보를 저장하려면 프로그램은 다음과 같은 세 가지를 알아야 한다.

  • 어디에 저장되는가?
  • 어떤 값이 저장되는가?
  • 어떤 종류의 정보인가?

 

데이터형은 정보의 종류를 나타내고, 변수 이름은 그 값을 기호로 나타낸 것이다. & 연산을 사용하면 변수의 메모리 주소를 알아낼 수 있다.

 

변수 이름

 

두 개 이상의 단어를 결합하여 변수 이름을 지을 때는, 밑줄로 단어를 구분하거나 첫 단어를 제외하고 각 단어의 첫문자를 대문자로 쓰는 것이 관례이다.

변수 이름을 지을 때는 다음과 같은 간단한 규칙을 따라야 한다.

  1. 변 수 이름에는 영문자, 숫자, 밑줄(_) 문자만을 사용할 수 있다.
  2. 숫자를 변수 이름의 첫 문자로 사용할 수 없다.
  3. 변수 이름에서 대문자와 소문자는 구별된다.
  4. C++의 키워드는 변수 이름으로 사용할 수 없다.
  5. 두 개의 밑줄 문자로 시작하는 이름이나, 밑줄 문자와 대문자로 시작하는 이름은, 그것을 사용하는 컴파일러와 리소스가 사용하기로 예약되어 있다.
  6. 변수 이름의 길이는 제한이 없으며, 변수 이름에 쓰이 ㄴ모든 문지들이 유효하다.

 

 

 

정수형

정수는 소수부가 없는 수를 말한다. C++의 여러 정수형들은 서로 다른 크기의 메모리를 사용하여 정수를 저장한다. 정수를 저장하는데 사용되는 메모리의 크기를 폭이라 한다. 메모리의 크기가 클수록 폭이 넓다.

short, int, long, long long 정수형

int, short, long 세 가지 데이터형은 부호가 있는 데이터형으로, 나타낼 수 있는 양의 정수값과 음의 정수값의 범위가 거의 같다.

정수의 크기를 아는 방법

  1. sizeof 연산자를 사용 : sizeof 연산자는 변수나 데이터형의 크기를 바이트 단위로 리턴
  2. 여러가지 정수형들의 범위에 대한 정보가 들어있는 climits 헤더 파일을 열어보는 것

 

예제 1번 : limits.cpp

// 정수 한계값
  
#include <iostream>
#include <climits>              // 구식 C++에는 limits.h를 사용한다
int main()
{
    using namespace std;
    int n_int = INT_MAX;        // n_int를 int형의 최대값으로 초기화
    short n_short = SHRT_MAX;   // limits.h 파일에 정의된 기호 상수
    long n_long = LONG_MAX;

    // sizeof 연산자는 데이터형이나 변수의 크기를 알아낸다
    cout << "int는 " << sizeof (int) << " 바이트이다." << endl;
    cout << "short는 " << sizeof n_short << " 바이트이다." << endl;
    cout << "long은 " << sizeof n_long << " 바이트이다." << endl;
    cout << endl;

    cout << "최대값:" << endl;
    cout << "int: " << n_int << endl;
    cout << "short: " << n_short << endl;
    cout << "long: " << n_long << endl << endl;
    cout << "long long: " << n_llong << end1 << end1;
    cout << "int의 최소값 = " << INT_MIN << endl;
    cout << "char의 비트 수 = " << CHAR_BIT << endl;
    return 0;
}

 

 

sizeof 연산자와 climits 헤더 파일

sizeof 연산자는 데이터형 이름이나 변수 이름에 모두 사용할 수 있다. 데이터형 이름에 사용할 때는 괄호를 사용해야 하며, 변수 이름에 사용할 때는 괄호가 없어도 상관없다.
climits 헤더 파일은 데이터형의 한계값을 나타내기 위해 기호 상수를 사용한다.

 

초기화

초기화는 선언과 대입을 하나로 조합한다. 함수 안에서 정의된 어떤 변수를 초기화하지 않으면 그 변수의 값은 미확정 상태가 된다. 미확정 상태라는 말은 그 변수가 생성되기 바로 직전에 그 메모리 위치에 우현히 남아있던 것이 그 변수의 값으로 행세한다는 것을 의미한다.

변수가 어떤 초기값을 가져야 하는지 분명히 알고 있다면 반드시 초기화하라. 변수를 선언할 때 아예 값을 대입하여 초기화까지 하면, 나중에 잊어버려고 변수에 값을 대입하지 않는 실수를 예방할 수 있다.

 

unsiged형

unsigned형을 사용하면 그 변수에 저장할 수 있는 최대값을 늘릴 수 있다.

 

예제 2번 : exceed.cpp

// 정수 한계값을 초과한다
  
#include <iostream>
#define ZERO 0		// 값 0으로 대체될 기호 상수 ZERO를 정의한다
#include <climits>	// INT_MAX가 int형의 최대값으로 정의되어 있다

int main()
{
	using namespace std;
	short Dohee = SHRT_MAX;			// 변수를 최대값으로 초기화
	unsigned short Insuk = Dohee;		// Dohee가 정의되어 있으므로 맞다

	cout << "도희의 계좌에는 " << Dohee << "원이 들어 있고, ";
	cout << "인숙이의 계좌에도 " << Insuk << "원이 들어 있다." << endl;
	cout << "각각의 계좌에 1원씩 입금한다." << endl << "이제 ";
	Dohee = Dohee + 1;
	Insuk = Insuk + 1;
	cout << "도희의 잔고는 " << Dohee << "원이 되었고, ";
	cout << "인숙이의 잔고는 " << Insuk << "원이 되었다." << endl;
	cout << "이럴 수가! 도희가 나 몰래 대출을 했나?" << endl;
	
	Dohee = ZERO;
	Insuk = ZERO;
	cout << "도희의 계좌에는 " << Dohee << "원이 들어 있고, ";
	cout << "인숙이의 계좌에도 " << Insuk << "원이 들어 있다." << endl;
	cout << "각각의 계좌에서 1원씩 인출한다." << endl << "이제 ";
	Dohee = Dohee - 1;
	Insuk = Insuk - 1;
	
	cout << "도희의 잔고는 " << Dohee << "원이 되었고, ";
	cout << "인숙이의 잔고는 " << Insuk << "원이 되었다." << endl;
	cout << "이럴 수가! 인숙이가 복권에 당첨되었나?" << endl;
	return 0;
}

 

unsigned short형인 Insuk에서 1을 빼면 0에서 65,535로 갑자기 넘어간다. 즉, 표현할 수 있는 한계를 벗어나면 그 표현 범위의 반대편에서부터 다시 시작한다.

 

C++는 표현 한계값을 벗어날 때(오버플로와 언더플로가 발생할 때) 부호 없는 정수형의 경우에 항상 이와 같이 동작한다. 부호 있는 정수형의 경우에는 항상 이와 같이 동작한다고 보장할 수 없다. 그러나 현재 대부분의 C++는 이와 같은 방식으로 동작하고 있다.


 

 

어떤 정수형을 사용할 것인가?

 

일반적으로 int형은 컴퓨터에서 가장 “자연스러운” 정수 크기로 설정된다. 여기서 자연스러운 크기라는 것은 컴퓨터가 가장 효율적으로 처리하는 정수 형식을 말한다.
16비트로 나타낼 수 있는 정수보다 더 큰 정수를 나 타내야 할 때는 long형을 사용한다.

 

short형이 int형보다 크기가 작을 경우에는 short형을 사용하는 것이 메모리를 절약할 수 있다.

 

 

 

정수형 상수

정수형 상수는 프로그램에 직접 써 넣는 정수를 말한다. 정수형 상수에는 16진, 8진, 10진 등 다양하다.

예제 3번 : hexoct1.cpp

// 16진 정수형 상수와 8진 정수형 상수를 보여 준다
  
#include <iostream>
int main()
{
	using namespace std;
	int chest = 42;			// 10진 정수형 상수
	int waist = 0x42;		// 16진 정수형 상수
	int inseam = 042;		// 8진 정수형 상수

	cout << "손님 몸매는 한마디로 끝내 줍니다!\n";
	cout << "가슴둘레 " << chest << "\n";
	cout << "허리둘레 " << waist << "\n";
	cout << "인심길이 " << inseam << "\n";
	return 0;
}

 

어떤 정수값을 16진수나 8진수 형태로 출력하려면 cout의 특별한 기능을 사용해야 한다. iostream 헤더 파일은 새로운 행을 시작하라는 메시지를 ocut에 전달하는 endl 조정자를 제공한다.
이와 비슷하게, iostream 헤더 파일은 정수를 10진수, ㅇ6진수, 8진수로 각각 출력하라는 메시지를 cout에 전달하는 dec, hex, oxt 조정자를 제공한다.

 

예제 4번 : hexoct2.cpp

// 값을 16진수와 8진수로 출력한다
#include <iostream>
using namespace std;
int main()
{
    using namespace std;
    int chest = 42;
    int waist = 42;
    int inseam = 42;

    cout << "손님 몸매는 한마디로 끝내 줍니다!"  << endl;
    cout << "가슴둘레 " << chest << " (10진수)" << endl;
    cout << hex;        // 진법을 바꾸는 조정자
    cout << "허리둘레 " << waist << " (16진수)" << endl;
    cout << oct;        // 진법을 바꾸는 조정자
    cout << "인심길이 " << inseam << " (8진수)" << endl;
    return 0;
}

 

hex 조정자는 cout에게 어떻게 행동하라고 알리는 메시지이다. 식별자 hew는 std 이름공간의 일부이고, 이 프로그램이 std 이름 공간을 사용한다. 그렇기에 이 프로그램은 hex를 변수 이름으로 사용할 수 없다.


 

 

char형 : 문자와 작은 정수

 

프로그래밍 언어들은 문자를 수치 코드로 나타냄으로써 문자와 숫자를 저장한다. 대부분 컴퓨터 시스템들은 256개보다 적은 개수의 문자들을 지원한다. 이러한 문자들은 1바이트만으로 충분히 나타낼 수 있다.

 

예제 5번 : chartype.cpp

// char형

#include <iostream>
int main()
{
    using namespace std;
    char ch;     // char형 변수를 선언한다

    cout << "원하는 문자 하나를 입력하시오: " << endl;
    cin >> ch;
    cout << "감사합니다. ";
    cout << "당신이 입력한 문자는 " << ch << " 입니다." << endl;
    return 0;
}

 

입력할 때 cin은 키보드로 입력된 M을 값 77로 변환한다. 출력할 때 cout은 값 77을 문자 M으로 변환한다. 동일한 값 77을 int형 변수에 저장하면 ocut은 77을 출력한다.

 

 

예제 6번 : morechar.cpp

// char형과 int형의 비교

#include <iostream>
int main()
{
    using namespace std;
    char ch = 'M';  // M에 해당하는 ASCII 코드를 char형 변수 ch에 대입
    int i = ch;     // 같은 코드를 int형 변수 i에 저장
    cout << ch << "의 ASCII 코드는 " << i << "입니다." << endl;

    cout << "이 문자 코드에 1을 더해 보겠습니다." << endl;
    ch = ch + 1;    // ch에 있는 문자 코드를 변경한다
    i = ch;         // i에 새로운 문자 코드를 저장한다
    cout << ch << "의 ASCII 코드는 " << i << "입니다." << endl;

    // cout.put() 멤버 함수를 사용하여 char형 변수 ch를 출력한다
    cout << "cout.put(ch)를 사용하여 char형 변수 ch를 화면에 출력: ";
    cout.put(ch);

    // cout.put()을 사용하여 문자 상수를 출력한다
    cout.put('!');

    cout << endl << "종료" << endl;
    return 0;
}

 

 

멤버 함수 : cout.put()

 

cout.put()은 C++ 객체지향 프로그래밍에서 중요한 개념인 멤버 함수를 설명하는 첫번째 예이다. 멤버 함수는 클래스에 속하고, 클래스의 데이터를 다루는 방법을 정의한다.
멤버 함수는 그 클래스의 특정 객체를 통해서만 사용할 수 있다. cout과 같은 객체를 통해 멤버 함수를 사용하려면 마침표로 객체 이름과 함수 이름을 서로 연결해야 한다. 이 마침표를 멤버 연산자라고 부른다.

 

char형 상수

 

키보드를 통해 프로그램 만으로 직접 입력할 수 없는 문자들이 있다. 예를 들어, 개행 문자는 Enter 키를 누르는 방법으로는 문자열의 일부로 입력할 수 없다. 엔터 키를 누르면 프로그램 에디터는 개행 문자를 입력하지 않고, 새 행을 시작하라는 뜻으로 받아들인다.
C++는 이와 같은 특수 문자들을 위해 이스케이프 시퀀스(secape sequence)라는 특별한 표기법을 사용한다.

 

긴 문자열 안에 개행 문자를 삽입할 수 있다. 이것은 endl을 사용하는 것보다 훨씬 편리하다. 그러나 문자열을 출력할 때는 개행 문자로 끝내는 것이 타이핑 수고를 덜 요구한다.

cout << x << endl;	    // cout << x << "\\n";
cout<<"Dr. X.\\n";		// cout << "Dr. X." << endl;

 

 

예제 7번 : bondini.cpp

// 이스케이프 시퀀스를 사용한다

#include <iostream>
int main()
{
	using namespace std;
	cout << "\a암호명 \"화려한 외출\" 작전이 방금 개시되었습니다!\n";
	cout << "8자리 비밀번호를 입력하십시오:________\b\b\b\b\b\b\b\b";
	long code;
	cin >> code;
	cout << "\a입력하신 비밀번호는 " << code << "입니다.\n";
	cout << "\a비밀번호가 맞습니다! Z3 계획을 진행하십시오!\n";
	return 0;
}

 

벨소리와 함께 다음이 출력되었다.

 

 

유니버설 네임 코드

\u나 \U 중 어느 하나로 시작한다.

bool형

어떠한 수치 값이나 포인터 값도 bool 값으로 묵시적으로 변환될 수 있다. 0이 아닌 값들은 true로, 0 값은 false로 변환된다.


 

2. const 제한자

const 키워드를 사용하여 변수를 선안하고 초기화할 수 있다. 하지만 상수는 한번 초기화되면 그 값이 고정된다. 상수를 만드는 일반적인 형식은 다음과 같다.

const 데이터형 상수 이름 = 값;

 

const 상수는 선언할 때 초기화해야 하며, 다음과 같이 하는 것은 좋지 않다.

const int toes;
toes = 10;

 

const를 사용하면 좋은 이유

  1. 데이터형을 명시적으로 지정할 수 있다
  2. C++의 활동 범위 규칙에 의해 그 정의를 특정 함수나 파일에서만 사용할 수 있도록 제한할 수 있다.
  3. 배열이나 구조체와 같은 보다 복잡한 데이터형에도 const를 사용할 수 있다.

 

 

3장 1~2장 학습을 마치고

새벽에 비몽사몽으로 앞부분 학습을 하다 아침에 일어나서 나머지 부분을 이어서 했다. 기본적인 데이터형에 대해, 이스케이프 시퀀스에 대해서 배울 수 있었다.
아직 3장의 절반밖에 학습하지 못해 다 하려면 시간이 좀 많이 걸리겠지만, 하나하나 알아가는 즐거움이 쏠쏠하다. 난 게임 엔진을 배울 때보다 이렇게 프로그래밍 언어를 공부할 때가 훨씬 더 재미있다는 걸 느끼고 있다.

정수형에 대해서 배웠으니 이제 부동 소수점에 대해서 학습할 예정이다.