끝나지 않는 프로그래밍 일기


1-1. 변수(Variable)


변수(Variable)란 무엇일까요? 이미 익히 들어보신 분도 계실거라 생각합니다. 변수란 쉽게 말하면 값을 담아두는 기억 공간입니다. 변수는 하나의 데이터 값을 가질수 있으며, 한번 정해진 값은 고정되어 있는게 아니라 계속 변할수 있는 수입니다. 이는 즉, 대입되는 수가 항상 변할수가 있다는 말입니다. 또한, 이 변수는 담기는 음식에 따라 그릇이 달라지듯 담기는 데이터에 따라 변수의 자료형(Data Type)이 결정됩니다. 문자는 문자를 담을수 있는 자료형이 있으며, 정수는 정수를 담을수 있는 자료형이, 실수는 실수를 담을수 있는 자료형이 따로 존재합니다.


우선 C언어에서의 기본 자료형(Data Type)은 무엇이 있는지에 대해 간단히 보도록 하겠습니다. 아래의 표에서 자료형의 크기가 크면 클수록 값의 표현범위는 어떻고, 작으면 작을수록 값의 표현범위가 어떻게 달라지는지 유심히 살펴보시기 바랍니다.


자료형

크기

값의 표현범위

정수형

char

1바이트

-128이상 +127이하

short

2바이트

-32,768이상 +32,767이하

int

4바이트

 -2,147,483,648이상 +2,147,483,647이하

long

4바이트

-2,147,483,648이상 +2,147,483,647이하

long long

8바이트

-9,223,372,036,854,775,808이상

+9,223,372,036,854,775,807이하

실수형

 float

4바이트

±3.4 ×10^-37이상 ± 3.4 × 10^38이하

double

8바이트

 ±1.7 ×10^-307이상 ± 3.4 × 10^308이하

long double

8바이트 이상

 double 이상의 표현범위


정수형 자료형을 살펴보시면 char, short, int, long, long long이 있으며 실수형 자료형에는 float, double, long double이 있습니다. 이런 자료형이 여러개 존재하는 이유는 데이터 표현방식이 다르고, 효율적인 메모리 공간 활용을 하기 위함이며, 자료형의 크기가 클수록 값의 표현범위도 함께 커짐을 쉽게 알수 있습니다. 그리고 또 하나는 부호가 있느냐 없느냐에 따라서 부호가 있는 변수(signed)와 부호가 없는 변수(unsigned)로 나뉘게 됩니다.


구분

키워드

설명

부호가 있는 변수

signed

기본(default) 형식

부호가 없는 변수

unsigned

부호가 생략되면 unsigned 형식이며, 값의 표현범위가 두배 정도 늘어남


기본 자료형은 모두 부호가 있는(signed) 자료형이며, 양의 표현범위를 더 늘리기 위하여 unsigned 키워드를 붙여줄 수 있습니다. 만약 int에 unsigned를 붙여준다면 0이상 4,294,967,295이하의 수(unsigned int)를 표현할 수 있습니다. 하나 더 예를들어 long long에 unsigned를 붙여준다면 0이상 18,446,744,073,709,551,615이하의 수(unsigned long long)를 표현할 수 있게됩니다. (참고로 실수에는 unsigned가 붙을 수 없습니다.)


그렇다면 실제로 우리가 int 자료형을 사용하여 정수 데이터를 변수에 담으려고 한다면 어떻게 해야할까요? 우선 int 자료형을 앞에다 붙여야 한다는건 알고 있습니다. 그런데 이 변수에 접근을 하여 값을 가져오고 다시 담으려면 각 변수만이 가지고 있는 고유한 특징이 있어야 합니다. 그래야 변수를 구분하고 접근할 수 있으니까요. 다른 프로그래밍 언어도 마찬가지로 변수에는 변수명(=식별자)이라는 것이 존재하며, 이 변수명은 말 그대로 변수의 이름을 의미합니다. 물론 이 변수의 이름은 우리가 붙여줄 수 있습니다. 아래를 한번 보도록 합시다.


int num;


위의 코드가 의미하는 것은 무엇일까요? num이란 이름을 가진 int형 변수라는 것임을 알 수 있습니다. 그리고 이 num이란 변수의 이름을 가지고 이 변수에 정수형 값을 넣어줄 수 있습니다. 물론 값의 표현범위의 한에서만 말이죠.


num = 47;


위의 코드는 num이란 변수에 47이란 값을 대입(=)하는 코드입니다. 저렇게 값을 넣어주고서, 그 아래에 또다른 코드를 추가하여 다른 값을 또 넣을수 있습니다. 고정되어 있는 수가 아닌 항상 변할수 있는 수니까 가능한 얘기겠죠? 참고로 가장 마지막에 붙는 세미콜론(;)은 각 문장을 구분함으로써 한 문장이 끝나면 반드시 문장의 끝을 알리는 세미콜론(;)을 붙여주어야만 합니다.


한가지 더 알아두실게 있다면, 변수에 이름을 붙히기 전에도 조건이 있습니다. 첫번째 글자는 반드시 영어이어야 하며, 언더바(_) 기호를 문자로 취급하여 변수명에 사용이 가능합니다. 대소문자 구분이 가능하며(num과 Num는 다른 변수), 기본적으로 예약어는 변수명으로 사용할 수 없습니다. 여기서 예약어는 int, char, long, typedef, auto 등을 말합니다. 변수명 길이에 제약은 없으나 되도록이면 길게쓰지 않는게 좋습니다. 변수명을 기억하기가 더 어려워지고 오타를 입력할 가능성이 많아지기 때문에 바람직하지 않습니다. 


이제 변수에 대해 간략하게 정리를 해보았는데, 잠깐의 시간이나마 조금 더 깊숙히 들어가보도록 합시다.


1-2. 실제로 데이터가 기억되는 장소


실제로 데이터가 기억되는 장소는 어디일까요? 위에서는 변수란 값을 담아두는 기억 공간이라고 말했습니다. 사실 이 변수를 또 다르게 정의하면 변수란 값을 저장하고 참조할 수 있는 할당된 메모리 공간이라 얘기할 수 있습니다. 예를 들어보자면, int는 메모리에서 4바이트의 공간을 차지하며, double은 메모리에서 8바이트의 공간을 차지합니다. 아래와 같이 int형 변수 a를 만들었다고 가정해봅시다.


int a;


그리고 이것이 메모리 공간에서는 어떻게 표현이 되는지 아래의 그림을 보도록 합시다.


<10진수 정수형 변수 a의 메모리 할당>


임의의 공간에 4바이트 만큼의 메모리 공간을 할당하며, 컴파일러는 이 공간에다가 a라는 이름을 붙여줍니다. 이제 우리는 이 a라는 이름을 통하여, 이 공간에 접근을 할 수 있게 되는 것입니다. (변수는 하나의 주소값을 가지며, 이에 대한 설명은 후에 '포인터' 강좌에서 이어서 설명합니다.)


2. 상수(Constant)


위에서 배운 변수가 항상 변할수 있는 수라면 상수(Constant)는 고정되어 있는 수를 말합니다. 예를 들어서, 4x+6y=38란 식중 4,6,38은 상수이고 x,y는 등호만 성립하면 변경될수 있기 때문에 변수라 부릅니다. 프로그래밍에서 말하는 상수와 변수도 중학교 과정을 거칠때 배우는 변수, 상수와 크게 다를게 없습니다.


프로그래밍에서의 상수는 메모리 공간에 저장되어 있으나 변경할수 없으며, 상수에서 다시 리터럴 상수(Literal Constant)와 심볼릭 상수(Symbolic Constant)로 나뉘는데 리터럴 상수는 '이름을 지니지 않는 상수', 심볼릭 상수는 '이름을 지니는 상수'라고 생각하시면 됩니다. 값을 표기하면 컴파일러가 그 크기와 형태를 보고 적당한 자료형을 선택합니다. 상수를 표현하려면 const란 키워드를 자료형 앞에다 붙여주면 됩니다. 그렇다면 아래의 예에서 리터럴 상수와 심볼릭 상수를 구분해 보도록 할까요?


int num = 40 + 50;

const int A = 66;


위의 예제를 보자면 40과 50, 그리고 66은 자기 자신이 곧 상수를 의미하는 리터럴 상수이며 A는 이름을 가진 상수로써 심볼릭 상수라고 말할 수 있습니다. (심볼릭 상수는 매크로를 통하여 정의할 수 있지만 이는 나중에 설명하도록 하겠습니다.) const 상수는 대표적인 심볼릭 상수라고 말할 수 있습니다. 이 const 키워드가 붙으면, 변수에 저장된 값이 변경되는것을 막을수 있습니다. 한번 초기화 된 값은 변경하지 못하며, 초기화 값을 지정해주지 않아도 쓰레기 값으로 초기화 되어 선언 이후로부터 변경이 불가능합니다. 


참고로, 상수의 이름은 대문자로 표시하며, 둘 이상의 단어를 함께 묶을때는 언더바(_)로 단어를 이어서 이름을 짓습니다. 이것은 변수와의 구분을 쉽게 하기 위함이며, 많은 프로그래머 들이 선택하는 네이밍 규칙이기도 합니다.


접미사 

자료형

사용 예

u 혹은 U

unsigned int

304U

l 혹은 L

long

304L

ul 혹은 UL

unsigned long

304UL

f 혹은 F

float

3.15F

l 혹은 L

long double

3.15L


위의 표는 접미사에 따른 정수형 상수, 실수형 상수들의 예를 든것입니다. 위에서 말씀드렸듯이 '값을 표기하면 컴파일러가 그 크기와 형태를 보고 적당한 자료형을 선택한다' 라고 했었죠? 실제로 Visual Studio 2012를 실행하고, C 프로젝트를 생성하여 메인 함수 내에 다음과 같은 코드를 작성하면 컴파일 과정에서 경고 메시지를 볼 수 있습니다.


float f1 = 3.14;


warning C4305: '초기화 중' : 'double'에서 'float'(으)로 잘립니다.


왜냐하면 3.14는 8바이트 double형 상수로 생각하며, 이 값을 저장하는 변수는 4바이트 float형이기 때문에 값이 잘려나갈수 있음을 경고한 것입니다. 이때는 3.14f와 같이 f 접미사를 붙여 float형 상수로 자료형을 변경시킬 수 있습니다. (3.14가 float형으로 충분히 표현할 수 있음에도 불구하고, 따로 f 접미사를 붙여주어야 하는 이유는 부동소수형 상수, 즉 실수는 기본적으로 double형이라고 간주해버리기 때문입니다.)