모두의 코드
씹어먹는 C 언어 - <3. 변수가 뭐지? >

이번 강좌에서 배우게 될 것은

씹어먹는 C 언어

안녕하세요? 여러분. 잘 지내셨나요. 지난 번에 처음으로 C 코드를 분석한 것은 이해가 잘 되셨나요? 이해가 잘 안되셨다도 괜찮습니다. 점점 C 언어를 배워감에 따라, 기존이 이해가 안 되었던 것들도 언젠가는 '아 이래서 그랬구나' 하는 순간이 오게 됩니다. 이 단계에서 여러분이 취해야 할 자세는 일단 이해가 안되는 것은 일단, 암기 하고, 포기하지 않는 것이 필요합니다.

변수란 무엇인가?

컴퓨터는 많은 내용을 기억 해야 합니다. 정확히 말하면, 컴퓨터의 '메모리' 라는 부분에 전기적인 신호를 써 놓는 것이죠. 컴퓨터가 무엇을 기억해야 되냐고 생각할 수 있지만, 우리가 많이 하는 게임인 스타크레프트만 보아도 일단, 각 유닛의 HP 와 마나, 그리고 실시간으로 바뀌는 미네랄과 가스, 뿐만 아니라 유닛의 위치, 유닛의 데미지 등 모든 것을 기억해야지 우리가 게임을 제대로 즐길 수 있게 되겠지요. 만약 컴퓨터가 미네랄의 양을 제대로 기억 못한다면 미네랄이 갑자기 100 에서 0 이 되거나 10 에서 9999 로 바뀌는 참사가 발생합니다.

그렇다면 컴퓨터는 이러한 데이터들을 어떻게 기억할까요? 바로 컴퓨터의 메모리, 즉 RAM 이라는 특별한 기억공간에 이를 기록합니다. 보통 우리는 흔히 RAM 을 설명할 때 아래 처럼 표시합니다.

마치, 각 방에 데이터들이 저장됩니다. 이 때, 컴퓨터는 각 방에 이름을 붙이는데 단순하게 숫자로 이름을 붙입니다. 0 번, 1 번, 2 번, .. 와 같이 말입니다. 우리 대부분이 사용하는 32 비트 CPU 에서는 최대 2³² 개(4GB) - 총, 42 억개 달하는 방을 가질 수 있게 되겠지요. 참고로 32 비트 숫자를 매번 쓰는게 매우 힘들기 때문에, 대개 16진법으로 주소값을 나타냅니다.

예를 들어서, 컴퓨터가 0x12345678 부터 0x1234567B 부분에 내가 캔 미네랄의 양에 관한 정보를 저장했다고 합시다. (이 한칸에는 1 바이트, 즉 0 부터 127 까지의 수 데이터를 저장할 수 있습니다) 만약 우리가 건물을 지을 때, 내가 가진 미네랄의 양이 충분한 지 확인하기 위해, 내가 캔 미네랄의 양에 관한 정보가 필요합니다. 그런데, 이렇게 미네랄에 관한 정보가 필요로 할 때 마다 이 길고 알아보기 힘든 복잡한 주소를 일일이 써야 한다면 상당히 힘들겠지요.

하지만 다행히도 C 언어에는 '변수' 라는 것이 있어서, 이 모든 작업을 쉽게 할 수 있습니다. 예를들어, 내가 캔 미네랄의 양을 mineral 이라는 변수에 저장했다고 합시다. 그렇다면 컴퓨터는 '알아서' 메모리의 어딘가에 mineral 의 방을 주고 그 내용을 저장합니다. 예를들어서, 컴퓨터가 이 mineral 이라는 변수에게 4 칸의 자리를 할당해 주었다고 합시다. 이는 아래 그림처럼 메모리 상에 표시됩니다.

이 때, 우리가 미네랄을 더 캐서 8 을 추가해야한다고 봅시다. 만약 이전에 8 을 추가한다면 0x12345678 부터 0x1234567B 까지의 모든 내용을 불러와서 8 을 더한 후, 다시 집어넣는 작업을 일일이 손으로 써 주어야 되었을 것입니다. 하지만, 이제는 단순히 mineral = mineral + 8 과 같이 써 주기만 한다면 mineral 에 8 이 더해지는 것이죠. (만약 mineral = mineral + 8 이라는 식이 이해가 안되도 그냥 넘어가세요. 이 처럼 간단해 진다는 것을 말해주고 싶었을 뿐입니다)

이와 같이 C 언어에서, 바뀔 수 있는 어떤 값을 보관하는 곳을 변수 라고 합니다. 영어로는 Variable 이라 하는데, 말 그대로 '바뀔 수 있는 것들' 이라는 뜻입니다.

변수 선언하기

/* 변수 알아보기 */
#include <stdio.h>
int main() {
  int a;
  a = 10;
  printf("a 의 값은 : %d \n", a);
  return 0;
}

  프로젝트를 만들어 위의 내용을 적은 후, 컴파일 해봅시다. 까먹었다면 1 강을 참조하세요. 만약 성공적으로 하였다면 아래와 같은 화면을 볼 수 있겠죠.

  일단, 이번에도 역시 생소한 것들이 나왔기 때문에 한 문장씩 차근차근 살펴 봅시다.

int a;

음, 이게 무엇일까요? 이전에 int main() 에서 보았던 int 가 다시 나타났군요.사실 이 문장에 뜻은 a 라는 변수를 우리가 쓰겠다고 컴파일러에게 알리는 것입니다. 만약 이러한 문장이 없다면 우리가 x 가 뭐고 y 가 뭔지 알려주지도 않은 채, 친구에게 x + y 가 얼마냐? 하고 물어보는 것과 똑같은 격이 되는 것이지요.

이 때, a 앞에 붙은 int 라는 것은'int' 형의 데이터를 보관한다는 뜻으로, int 형의 변수는 -2147483648 에서 부터 2147483648 까지의 숫자를 보관 할 수 있게 됩니다. 따라서, 만약 중간의 문장을

a = 10000000000000;

와 같이 한다면 아마 a 의 값을 출력하였을 때, 이상한 결과가 나오게 됩니다. 왜냐하면 보관할 수 있는 범위를 초과하는 숫자를 보관했기 때문이죠.

그럼 이제, 걱정이 생깁니다. a 에 고작 10 밖에 안 넣을 거 면서, 굳이 2147483647 ~ 2147483647 까지 표현할 수 있는 int 형의 변수를 왜 사용했냐고 물을 수 있습니다. 물론, int 형 보다 작은 범위의 숫자 데이터 만을 가지는 형식이 있기는 하지만 (char 등등), 보통의 경우 정수 데이터를 보관할 때 int 형 변수를 사용합니다.

또한, 2147483647 보다 큰 수를 사용하려면 어떻게 해야되냐는 궁금증도 생기지요. 물론 이 보다도 훨씬 큰 숫자를 처리하는 데이터 형식이 있습니다. 아래의 표를 참조하세요.

http://www.cplusplus.com/doc/tutorial/variables/

세번째 열인 Range 를 보시면, unsignedsigned 라고 나뉜 것이 있는데, 보통 int 라 하면 signed int 를 뜻합니다. 이는 음수/양수 모두 표시할 수 있는 대신에 양수로 표현할 수 있는 범위가 줄어듭니다. 반면에 unsigned int 는 양수만을 표현할 수 있는 대신에, 양수로 표현할 수 있는 범위가 두 배로 늘어납니다. 또한 마지막에 보면 float, double, long double 이 있는데 이들은 '실수형' 자료형으로 소수(0.1, 1.4123 등) 을 표현 할 수 있습니다. 뿐만 아니라 double 의 경우,

$$ \pm 2.3 \times 10^{-308} \backsim \pm 1.7 \times 10^{308} $$

의 수들을 표현 할 수 있습니다. (이에 대한 정확한 설명은 후에 다루겠습니다.)

a = 10;

위 문장은 무엇을 의미할까요? 언뜻 보기에도 감이 오시겠지만, 변수 a 에 10 을 집어넣는 다는 것입니다. 따라서 나중에 a 의 값을 출력시 10 이 나올 것입니다. 이와 같은 형태의 문장은 후에, 연산자에 대해 다룰 때 다시 알아보도록 하겠습니다.

printf("a 의 값은 : %d \n", a);

마지막으로, 지난번에도 보았던 printf 문 입니다. 그런데, 약간 다른 것이 있습니다. %d 가 출력되는 부분에 써져 있습니다. 그런데, 프로그램을 실행시켜 보았을 때 %d 는 컴퓨터에서 출력되지 않았습니다. 그 대신, %d 가 출력될 자리에 무언가 다른 것이 출력되었는데, 바로 a 의 값 이였습니다. 즉,%da 의 값 (정확히는 처음 "" 다음에 오는 첫 번째 변수) 을 '10 진수' 로 출력하라' 라는 뜻이 됩니다.

또 다른 예제를 봅시다.

/* 변수 알아보기 2*/
#include <stdio.h>
int main() {
  int a;
  a = 127;
  printf("a 의 값은 %d 진수로 %o 입니다. \n", 8, a);
  printf("a 의 값은 %d 진수로 %d 입니다. \n", 10, a);
  printf("a 의 값은 %d 진수로 %x 입니다. \n", 16, a);
  return 0;
}

프로그램을 제대로 짰다면 아래와 같은 결과를 볼 수 있을 것입니다.

일단, 위 코드를 보고 생기는 궁금증은 2 가지 있습니다. % 달린게 2 개나 있는데, 이를 어떻게 해야되냐와, %d 말고도 %o%x 는 무엇인가 입니다.

먼저, printf 의 작동 원리에 대해 봅시다.

printf 출력시에, 큰 따옴표로 묶인 부분 뒤에 나열된 인자들 (8, a) 가 순서대로 큰 따옴표 안의 % 부분으로 들어감을 알 수 있습니다. 따라서 , 예를들면 printf("%d %d %d %d", a,b,c,d); 와 같은 문장은 a, b, c, d 의 값이 순서대로 출력되겠죠.

이제, %o  와 %x 는 무엇일까요? 이는 인자의 값(a) 를 출력하는 형식 입니다. 즉, %oa 의 값을 8 진수로 출력하라라는 뜻이고, %x 는 16 진수로 출력하라는 뜻 이죠.

실수형 변수

앞서 말했듯이, 실수형에는 floatdouble 이 있습니다. double 의 경우 int 형에 비해 덩치가 2 배나 크지만 그 만큼 엄청난 크기의 숫자를 다룰 수 있습니다. 그 대신, 처음 15 개의 숫자들만 정확하고 나머지는 10 의 지수 형태로 표현됩니다. 또한 floatdouble 의 장점은 소수를 표시할 수 있다는 점인데, 정수형 변수에서 소수를 넣는다면 (예를들어 int a; a = 1.234;), 소수 부분은 다 잘린 채, 나중에 a 의 값을 표시해 보면 1 이 나올 것 입니다.

/* 변수 알아보기 3*/
#include <stdio.h>
int main() {
  float a = 3.141592f;
  double b = 3.141592;
  printf("a : %f \n", a);
  printf("b : %f \n", b);
  return 0;
}

  실행해 본다면 아래와 같이 나오게 됩니다.

   일단, 위 코드를 보면서 궁금한 점이 생기지 않았나요?

float a = 3.141592f;
double b = 3.141592;

왜, float 형 변수 a 를 선언할 때 에는 숫자 뒤에 f 를 붙였는데 double 형 에서는 f 를 안 붙였는 지요. 왜냐하면, 그냥 f 를 안 붙이고 float a = 3.141592 로 하면 이를 double 형으로 인식하여 문제가 생길 수 있습니다. 따라서, float 형이라는 것을 확실히 표시해 주기 위해 f 를 끝에 붙이는 것입니다.

printf("a : %f \n", a);
printf("b : %f \n", b);

이제, 마지막으로 %d, %o, %x 도 아닌 %f 가 등장하였습니다. 만약, 여기서 a%d 형식으로 출력하면 어떻게 될까요? 한 번 해보세요. 아마 이상한 숫자가 나오게 될 것입니다. 왜냐하면 a 는 지금 정수형 변수가 아니기 때문 입니다. 설사, 우리가 a = 3f; b = 3; 라고 해도, 이미 ab 를 실수형 변수로 선언하였기 때문에 컴퓨터는a ,b 를 절대 정수로 보지 않습니다.

따라서, 우리는 실수형 변수를 출력하는 형식인 %f 를 사용해야 합니다.

참고로 주의할 사항은 printf 에서 %f 를 이용해 수를 출력 할 때 다음과 같이 언제나 소수점을 뒤에 붙여 주어야 한다는 점입니다. 예를 들어서

printf("%f", 1);

을 하면 화면에 이상한 값 (아마도 0 이 출력될 것입니다) 이 나오지만

printf("%f", 1.0);

을 하면 화면에 제대로 1.0 이 출력됩니다.

printf 의 또 다른 형식

/* printf 형식 */
#include <stdio.h>
int main() {
  float a = 3.141592f;
  double b = 3.141592;
  int c = 123;
  printf("a : %.2f \n", a);
  printf("c : %5d \n", c);
  printf("b : %6.3f \n", b);
  return 0;
}

만약 위 소스를 성공적으로 쳤다면 실행시 아래와 같이 나오게 됩니다.

printf("a : %.2f \n", a);

이번에는 %f 가 아니라 %.2f 로 약간 다릅니다. 그렇다면 .2 가 뜻 하는 것은 무엇일까요? 대충 짐작했듯이, 무조건 소수점 이하 둘째 자리 까지만 표시하라 란 뜻입니다. 따라서, 위의 경우 3.1415923.14 까지만 출력되고 나머지는 잘리게 되죠.

여기서 '무조건' 이라는 것은 %.100f 로 할 경우에도, 3.141592000000....00 을 표시해서 무조건 100 개를 출력하게 합니다.

printf("c : %5d \n", c);

이번에는 %d 가 아닌 %5d 입니다. 여기서 .5 가 아님을 주의합시다. 이 말은, 숫자의 자리수를 되도록 5 자리로 맞추라는 것입니다. 따라서, 123 을 표시할 때, 5 자리를 맞추어야 하므로 앞에 공백을 남기고 그 뒤에 123 을 표시했습니다.

그런데, 123456 을 표시할 때, %5d 조건을 준다면 어떻할까요? 이 때는 그냥 123456 을 다 표시합니다. 앞서 .?f? 의 수 만큼 무조건 소수점 자리수를 맞추어야 하지만 이 경우는 반드시 지켜야 되는 것은 아닙니다

printf("b : %6.3f \n", b);

마지막으로, 위에서 썼던 두 가지 형식을 모두 한꺼번에 적용한 모습입니다. 전체 자리수는 6 자리로 맞추되 반드시 소수점 이하 3 째 자리 까지만 표시한다는 뜻입니다.

변수 작명하기

앞서, 보았듯이 변수를 선언하는 것은 어려운 일이 아닙니다. 단지, 아래의 형태로 맞추어 주기만 하면 됩니다.

(변수의 자료형) 변수1, 변수2, .....;
/* 예를 들어 */
int a, b, c, hi;
float d, e, f, bravo;
double g, programming;
long h;
short i;
char j, k, hello, mineral;

이 때, 변수 선언시 주의해야 할 점이 있습니다. 만약에 여러분이 오래된 버전의 C 언어 (C89) 를 사용한다면, 변수 선언시 반드시 최상단에 위치해야 합니다. 하지만, 여러분이 지금 사용하고 있는 최신 버전의 C 의 변수 사용하기 전 아무데나 변수를 선언해도 상관 없습니다.

/* 변수 선언시 주의해야 할 점 */
#include <stdio.h>
int main() {
  int a;
  a = 1;
  printf("a 는 : %d", a);
  int b;  // 괜찮음!
  return 0;
}

두 번째로, 사람의 이름을 지을 때, 여러가지를 고려하듯이 변수의 이름에서도 여러가지 조건들이 있습니다. 아래 예제를 보세요.

/* 변수 선언시 주의해야 할 점 */
#include <stdio.h>
int main() {
  int a, A;  // a 와 A 는 각기 다른 변수 입니다.
  int 1hi;
  // (오류) 숫자가 앞에 위치할 수 없습니다.
  int hi123, h123i, h1234324;  // 숫자가 뒤에 위치하면 괜찮습니다.
  int 한글이좋아;
  /*
  (오류)
  변수는 오직 알파벳, 숫자, 그리고 _ (underscore)로만으로 이루어져야 합니다. */
  int space bar;
  /*
  (오류)
  변수의 이름에는 띄어쓰기하면 안됩니다.  그 대신 _ 로 대체하는 것이 읽기
  좋습니다.*/
  int space_bar;  // 이것은 괜찮습니다.
  int enum, long, double, int;
  /* (오류)
     지금 나열한 이름들은 모두 '예약어' 로 C 언어에서 이미 쓰이고 있는
     것들입니다. 따라서 이러한 것들은 쓰면 안됩니다. 이를 구분하는 방법은
     예약어들을 모두 외우거나 '파란색' 으로 표시된 것들은 모두 예약어라 볼 수
     있습니다   */

  return 0;
}

  이 안에 모든 내용이 들어 있습니다. 변수의 이름은 반드시

 또한 C 언어는 대소문자를 구분합니다(이를 영어로 case sensitive 하다고 합니다). 따라서, VARiableVariable 은 다른 변수 입니다. 왠지, 조건이 많아 변수명을 지을 때, 까다로울 것 같지만 그냥 평범하게 짓다보면 예약어와 겹칠일 도 없고, 숫자가 앞에 오는 경우도 별로 없습니다.

자, 이제 우리는 C 언어에서 중요한 부분인 변수에 대해서 알아보았습니다. 현재 우리는 수를 다루는 변수들만 다루었지만, 다음 강좌에서는 변수에 대한 산술 연산과, 문자를 다루는 변수에 대해 알아보도록 하겠습니다.

강좌를 보다가 조금이라도 궁금한 것이나 이상한 점이 있다면꼭 댓글을 남겨주시기 바랍니다. 그 외에도 강좌에 관련된 것이라면 어떠한 것도 질문해 주셔도 상관 없습니다. 생각해 볼 문제도 정 모르겠다면 댓글을 달아주세요.

현재 여러분이 보신 강좌는 <<씹어먹는 C 언어 - <3. 변수가 뭐지? >>> 입니다. 이번 강좌의모든 예제들의 코드를 보지 않고 짤 수준까지 강좌를 읽어 보시기 전까지 다음 강좌로 넘어가지 말아주세요


 다음 강좌 보러가기
프로필 사진 없음
댓글에 글쓴이에게 큰 힘이 됩니다