글수 49
#05.초보가 쓰는 C 언어 강좌
(상수와 문자열)
05.00 상수에 대해
상수에는 크게 2가지로 나눌 수 있습니다. 리터럴 상수와 const 를 이용한 기호상수가 있습니다.
상수는 변수와 달리 변하지 않는 수입니다. 따라서 상수는 변수와 달리 대입 연산을 할 때 왼쪽에 위치하면 에러가 생깁니다.
다시 설명하자면
2 = 5 ;
이런 문은 불가능합니다.( C와 대부분의 프로그래밍 언어에서 대입(더 정확히 말하자면 assignmnet : 할당입니다)과 같다는 의미를 서로 다르게 표시합니다. C 에서 대입은 = 로 같다는 == [=이 두개] 로 표시합니다. 연산자에 설명할 때 좀 더 설명하겠습니다. )
따라서 대입연산자 왼쪽에 있을 수 없습니다.
05.01 리터럴 상수 (literal constant)
Literal 이라는 말은 우리말로 "문자의, 문자 그대로의" 라는 의미를 가지고 있습니다.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
int var; /* 1) */
var = 1; /* 2)값 대입 */
printf("%d \n", var); /* 3) */
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------
앞의 예제에서 var 의 값을 초기화하기 위해 사용된 1 이라는 숫자 같은 것을 리터럴 상수라고 합니다. 쉽게 설명하자면 그냥 그대로의 숫자, 문자를 리터럴 상수라고 합니다.
05.02 정수형 리터럴 상수
정수 리터럴상수를 이용하기 위해서는 십진법은 앞에 0이(숫자 0입니다. 영문자 o랑 혼돈하지 마세요.) 안 붙는 형태로 쓰고, 8진법은 숫자 앞에 0 이 붙는 형태, 16진법은 숫자 앞에 0x (또는 대문자 0X , 역시 숫자 0입니다.) 를 숫자 앞에 붙입니다.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
int var; /* 1) */
var = 11; /* 2)값 대입 */
printf("%d \n", var); /* 3) */
system("PAUSE");
return 0;
}
----------------------------------------------------------------------------
위에 예제에서, 주석 2) 에서 10 이라는 수를 10진수로 리터럴 상수로 이용했습니다. 조금 바꿔보면
var = 011; /* 2)값 대입 */
이라고 11 라는 숫자 앞에 0 하나를 붙여주세요. 그러면 결과로 뭐가 나오는 지 확인해 보세요.
결과는 9가 나옵니다. 왜, 이럴 까요. 앞에 0 이, 이 수는 8진수라고 알려줍니다. 그래서 8진수 9는 10진수로 9가 됩니다. 그래서 이러한 현상이 발생했습니다. 이제
var = 0x11; /* 2)값 대입 */
라고 하면 어떻게 될까요. 16진수 11은 10진수로 17이므로 17이 출력됩니다.
( 컴퓨터에서 기본적으로 모든 것이 2진수로 표현합니다. 2진수를 그냥 쓸 경우 긴 숫자단위가 필요합니다. 2진수로 255 라는 수를 표현하기 위해서는 8자리나 필요하게 됩니다. 그래서 이 2진수를 몇 자리씩 묶어 표현한니다. 3자리씩 묶으면 8진수로 표현할 수 있고, 4자리씩 묶으면 16진수로 표현 가능합니다.255 라는 10진수를 8진수로 표현하면 0377로 표현하고, 16표현하면 0xFF 입니다. )
그냥 정수형 리터럴 상수를 이용하면 숫자의 표현범위가 int 형과 같습니다. 그전의 16비트 컴퓨터 시스템에서는 int 형이 16비트 표현되었습니다. 이러다 보면 long 값이 4바이트인데 값을 대입하면서 값의 윗자리가 잘리는 경우가 있습니다. 이를 방지하기 위해 숫자 뒤에 L (소문자 l 도 가능, 그러나 숫자 1과 소문자 l 을 구별하는 게 좀 불편할 수 있으므로 대문자 L 을 추천합니다.) 이라는 값을 덧붙여 주었습니다. 요즘 컴파일러에서는 그렇게 큰 의미는 없겠지만 좀 안 좋은 환경에서 프로그래밍 하는 분을 이것을 고려해 주기 바랍니다.
long var = 0x12345678L
/* int 와 long 의 크기가 다른 경우 이렇게 long 인 것 표시한다./
이 부분은 굳이 이해할 필요없습니다. 모르겠으면 그냥 넘어가세요.*/
05.03 실수형 리터럴 상수
실수 (컴퓨터에서 실수라고 하면 소수(小數)점을 포함한 수입니다.)에 대해서는 오직 10진법만 사용됩니다. 수 앞에 0을 붙여도 그냥 10진수로 인식하고 0x 를 붙이면 오류를 발생합니다.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
double var; /* 1) */
var = 011.1; /* 2)값 대입 */
printf("%f \n", var); /* 3) */
system("PAUSE");
return 0;
}
----------------------------------------------------------------------------
출력은 그냥 11.1 입니다.
var = 0x11.1; /* 2)값 대입 */
라고 고치면 오류를 발생합니다.
실수형 리터럴 상수를 그냥 사용하면 double 형과 크기가 같습니다. 그래서 float 값을 사용하는데 문제가 생길 수 있습니다.
주석 1)대신
float var; /* 1) */
넣으면 경고가 생긴니다. ( visual c++6.0 에서는 나는데 Dev-cpp 에서는 그냥 컴파일 한다.) 경고가 생긴다고 컴파일이 안 되는 것은 아닙니다. 다만 별로 좋은 코드는 아닙니다. float 형임을 명시적으로 보여주기 위해서는 숫자 뒤에 f (또는 대문자 F도 가능합니다.) 를 붙입니다.
주석 2) 를
var = 011.1f; /* 2)값 대입 */
라고 고치는 게 좋습니다.
5.4 아스키코드 그리고 문자형 상수
앞 강의에서 문자형에서 문자 하나에 작은 따옴표를 붙이는 형식을 보았습니다. 이 방법으로 문자형 리터럴 상수를 만들 수 있습니다. 문자하나에(오직 문자 하나입니다.) ' ' (작은 따옴표) 를 붙이면 내부적으로 아스키코드로 인식합니다. 아스키코드는 문자를 컴퓨터로 저장할 수 있도록, 문자에 적당한 숫자를 부여한 규정입니다. 'a' 는 아스키코드 값 97을 갖습니다.
다음 예제에서 확인하세요.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d \n", 'a');
system("PAUSE");
return 0;
}
----------------------------------------------------------------------------
이 예제는 97 이라는 값을 출력합니다. 만일 'a' 라는 표현방식으로 그 값의 아스키코드를 표시하지 못했다면 불편한 점이 많이 있었을 것입니다. a 를 출력하기 위해서는
printf("%c \n", 97); /* 여기서 %c 는 한 문자를 출력할 때 사용됩니다. */
라고 %c를 이용하면 됩니다.
우리는 굳이 이 아스키코드 값을 외울 필요가 없이 작은 따옴표로 문자를 감사 주기만 하면 됩니다.
따라서
printf("%c \n", 'a');
를 이용해서 a라는 문자를 출력할 수 있습니다.
( 안타깝게 한글은 '한' 이런 식으로 하면 에러가 납니다. 한글은 아스키코드 한 글자로 표현할 수 없습니다. 이럴 때는 어쩔 수 없이 문자열 상수를 이용해야 합니다. )
(여기서 문자라고 하는 것은 단순히 영문자 뿐만 아니라 숫자글자:0부터 9까지의 숫자, 기호:~, !, <,> 까지 포함하는 개념입니다.)
5.5 문자열(문자열 상수)
앞에서 토근의 구성요소 중 하나가 문자열이라고 말했습니다. 문자 하나에 대해서는 그냥 문자 상수라고 해서 상수에 포함시키는데 반해, 문자열의 경우는 하나의 토큰으로 취급하고 있습니다. 그 이유는 문자 상수의 끝은 '\0'( \ 가 (이 글꼴 시스템에서는 윈화(한국 돈의 단위)를 표시하는 기호로 나오군요. 이 글이 어떻게 나올지 모르겠지만, 역 슬래시라고 불리는 기호가 나오는 경우도 있습니다. 표시되는 모양은 달라도 컴파일러는 다 같은 것으로 인식하니 걱정 안하셔도 됩니다. )으로 끝나기 때문입니다. 이 이유는 조금 나중에 다시 설명하고 문자열 상수를 표시하기 위해서는 문자들에(문자 하나 이상을 의미합니다) "Hello" 처럼, 큰 따옴표로 감싸야 합니다. 이 경우 크기가 글자수는 5자인데, 그 저장공간은 6byte입니다. 영문자 하나가 1바이트라서 5글자라서 5byte가 되고 끝에 문자가 끝났다는 표시로 '\0' 가 들어갑니다. '\0' 는 널(Null) 문자라고 불립니다. (나중에 나올 NULL 이라는 기호와 구별하기 바랍니다. 이 NULL은 Null 포인터라고 불립니다.)
문자열을 배웠으니 문자열예제를 보여드리겠습니다. 근데 이 예제는 우리가 처음에 본적이 있는 예제입니다.
-------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
printf("Hello, world \n");
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
우리가 처음에 배웠던 Hello, world라는 글자를 찍는 예제입니다. 우리도 모르게 이미 문자열 찍는 방법을 배웠군요. 이제 저 Hello, world 라는 글자 끝에 있는 \n의 정체에 대해 배워봅시다.
-------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
printf("Hello \n world!!");
printf("");
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
Hello
world!!계속하려면 아무 키나 누르십시오 . . .
------------------------------------------------------------------------
감을 잡으셨을 거라는 생각이 듭니다. \n은 글을 다음 줄로 내리는 효과를 발생시킵니다.
\ 가 들어 가는 문을 escape 문자라고 부릅니다. 약간의 특별한 역할을 하는 문자라고 생각하면됩니다.
이스케이프 문자에는 다음과 같은게 있습니다.
\' : 작은 따옴표를 표시합니다.
\" : 큰 따옴표를 표시합니다.
\\ : 문자 \ 를 표시합니다.
\t : 탭을 사용한 효과를 냅니디.
\n : 글을 다음줄로 보냅니다. 텍스트에디터에서 엔터친 효과와 비슷하죠.
\b : backspace 를 누른 것과 같은 효과를 냅니다. 앞의 글을 지웁니다.
\a : beep 음을 냅니다. 컴퓨터에서 삐 ~ 소리 냅 것 들은 적 있죠. 정말, 예전
컴퓨터 스타일로 냅니다. 조심하시길, 조금 귀에 거슬려서..
\n 대신에 다른 것을 넣어 실험해 보세요.
5.6 const 를 이용한 기호상수
우리가 앞서 배웠던 변수를 선언하는 방식에서 const 만 앞에 붙이면 기호상수를 선언 할 수 있습니다.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int var = 11 ;
printf("%d \n", var);
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
이제 상수 var 는 변수처럼 여러 번 대입 할 수 없습니다. 숫자 11 로 고정되는 것입니다.
다음 예제는 컴파일되지 않습니다. var = 22 에서 오류가 발생한다고 error가 나옵니다.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int var = 11 ; /* 1) */
var = 22;
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
위의 예제에서 주석 1) 에서 const 만 빼버린다면 변수이므로 에러 없이 컴파일 할 수 있습니다.
그래서 다음과 같은 것도 안됩니다.
----------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int var;
var = 11; /* 1) */
system("PAUSE");
return 0;
}
-------------------------------------------
주석 1)에서 error가 발생합니다. 그래서 선언과 동시에 초기화를 해야 합니다.
const int var;
var = 11;
를
const int var = 1;
로 할 수 있습니다.
const를 이용한 기호상수는 한 번 정의하고나 다른 값을 대입할 수 없으므로 선언함께 초기화를 해야 합니다.
왜, 이런 기호상수를 이용할 까요.
다음 예제를 보세요.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const double PI = 3.1415926535897932384626 ; /* 1) */
printf("%f\n", PI );
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
수학에서 사용하는 PI 같은 연산을 절대로 변할 수 없는 수입니다. 이런 PI 대신 리터럴 수로 직접 숫자를 쓴다고 해보세요. 얼마나 불편하겠습니까. PI의 경우 사람들이 많이 아는 상수이므로 큰 문제가 없겠지만 프로그램 안에서만 사용하는 특별하게 사용하는 숫자는 그 용도를 모르는 경우가 많겠지요. 그래서 그 용도까지 분명히 하면서 프로그래밍을 할 수 있도록 도와 주는 게 기호상수 입니다.
5.7 #define 문
# 가 들어가는 문은 전처리기에서 처리한다고 말한 적 있습니다. 이 전처리기가 무엇인지는 나중에 자세히 설명하겠습니다. 이 전처리기를 이용해서 상수를 표현하는 방법에 대해 예제만 보여주겠습니다.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define PI 3.1415926535897932384626
int main()
{
printf("%f\n", PI );
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
5.6 에서 설명한 예제를 조금 고쳤습니다. 이에 대한 설명은 나중에 합시다. 지금 이 글을 읽는 사람은 안 그래도 엄청나게 머리 아플 테니까.
다시 한 번 정리하겠습니다. 아직 리터럴 상수와 상수, 변수가 혼동할 것 같군요. (#define 에 대해서는 나중에 다시 배울테니 잠시 잊어 두셔요. )
우선 리터럴 상수는 숫자와 문자 그대로를 이용한 것 입니다. 문자 리터널 상수는 작은 따옴표나 큰 따옴표로 묶여 있습니다. 변수는 앞 강의에서 설명한 심볼로 이루어져 있습니다. 그리고 리터럴 상수를 이용해 초기화 합니다. 상수는 변수는 선언하는 방식으로 하되, 앞에 const 를 붙여 줍니다.
리터럴 상수는 처음이 작은 따옴표나 큰 따옴표 또는 숫자로 시작합니다. ( 16진수나 8진수를 표기 할 때도 0x 나 0 같이 숫자 0으로 시작합니다.) 그래서 리터럴 상수와 다른 것을 혼돈할 일은 없습니다. 그런데 const 를 이용한 상수와 변수는 오직 프로그래밍 짜는 사람들 마음대로 이름을 정하다 보니 혼돌될 염려가 있습니다. 그래서 여기에 보이지 않는 규칙이 하나 있습니다. const 를 이용한 상수를 대문자로 시작하는 것 입니다.
참고 사항
#1 8,16진수 표현에 대하여.
10진수를 표현하기 위해서는 10개의 기호가 필요합니다. 보통 우리는 아라비아 숫자를 사용합니다. 16진수를 표기하기 위해서는 6개의 숫자가 더 필요합니다. 컴퓨터에서는 보통 A, B, C, D, E (소문자로 표현해도 됩니다.) 까지의 알파벳을 이용합니다. C언어 형식을 따른다면 0xA는 십진수로 10을 나타내고, 0xB는 십진수 11,
0xF 는 십진수로 15 입니다.
2진수를 8진수, 16진수로 표현하기 쉽습니다. 그 역도 쉽습니다.
잠시 초점을 10진수에 맞추어 봅시다. 10진수를 1000 진수로 변환한다고 하고, 그 기호는 (xxx)식으로 괄호를 묶어 표현 해 보겠습니다.
1234578 이라는 수를 1000 진수로 표현하면 (1234)(5678) 입니다. 너무 당연하지 않습니까.
2진수와 8진수,16진수 관계도 이러합니다. 2진수를 8진수로 표현하기 위해서는 3자리씩 묶어 표현하고, 16진수로 표현하기 위해서는 4자리씩 묶어 표현하면 쉽습니다.
2진수 11101100 을 8진수로 표현하기 위해서는 (11)(101)(100)이런 식으로 뒤에서 3자리씩 묶고, 괄호 안의 수를 8진수로 표현하면, 8진수354 가 됩니다. 16진수로 표현하려면 (1110)(1100) 으로 묶으면 16진수 EC라고 표현할 수 있습니다.
#2 Lvalue 와 Rvalue
Lvalue : 왼쪽값[조금 이상하군요] 좌변값이라고 부르기도 합니다.
Rvalue : 우변값이라고 부르기도 합니다.
덧 글(덧붙이는 글)
너무 조급한 마음 가지지 마세요. 내가 일주일만에 C 를 완벽히 정복한다. 이런 마음은 안 가지시는 게 좋습니다. 완벽 정복은 시일이 많이 걸릴 수밖에 없습니다. 그 전에 말씀드렸다시피 프로그래밍 언어를 배우다 보면 필연적으로 컴퓨터 구조나, 알고리즘 등등이 필요합니다. 그래서 빠른 시일 안에 배우기 어렵습니다. 다만 자주 사용하는 내용은 빠른 시일에 배울 수 있습니다. 그래서 제 글에는 어려운 부분을 많이 빼두고 진행할 계획입니다. 그 부분은 잘 사용하면 알차게 프로그래밍 할 수는 있지만, 배우는 사람의 입장에서는 흥미를 잃기 쉽습니다. 좀 부족하더라도 전체 흐름을 읽는 게 중요하다고 생각합니다.
작성자 : 한밀(승룡)
버전 : 0.1.5
이 글은 계속 고쳐지고 있습니다.
2003년 12월 어느 추운 날
최종 수정일 : 2008년 2월 말, 2월인데 아직 눈이 내리다니..
(상수와 문자열)
05.00 상수에 대해
상수에는 크게 2가지로 나눌 수 있습니다. 리터럴 상수와 const 를 이용한 기호상수가 있습니다.
상수는 변수와 달리 변하지 않는 수입니다. 따라서 상수는 변수와 달리 대입 연산을 할 때 왼쪽에 위치하면 에러가 생깁니다.
다시 설명하자면
2 = 5 ;
이런 문은 불가능합니다.( C와 대부분의 프로그래밍 언어에서 대입(더 정확히 말하자면 assignmnet : 할당입니다)과 같다는 의미를 서로 다르게 표시합니다. C 에서 대입은 = 로 같다는 == [=이 두개] 로 표시합니다. 연산자에 설명할 때 좀 더 설명하겠습니다. )
따라서 대입연산자 왼쪽에 있을 수 없습니다.
05.01 리터럴 상수 (literal constant)
Literal 이라는 말은 우리말로 "문자의, 문자 그대로의" 라는 의미를 가지고 있습니다.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
int var; /* 1) */
var = 1; /* 2)값 대입 */
printf("%d \n", var); /* 3) */
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------
앞의 예제에서 var 의 값을 초기화하기 위해 사용된 1 이라는 숫자 같은 것을 리터럴 상수라고 합니다. 쉽게 설명하자면 그냥 그대로의 숫자, 문자를 리터럴 상수라고 합니다.
05.02 정수형 리터럴 상수
정수 리터럴상수를 이용하기 위해서는 십진법은 앞에 0이(숫자 0입니다. 영문자 o랑 혼돈하지 마세요.) 안 붙는 형태로 쓰고, 8진법은 숫자 앞에 0 이 붙는 형태, 16진법은 숫자 앞에 0x (또는 대문자 0X , 역시 숫자 0입니다.) 를 숫자 앞에 붙입니다.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
int var; /* 1) */
var = 11; /* 2)값 대입 */
printf("%d \n", var); /* 3) */
system("PAUSE");
return 0;
}
----------------------------------------------------------------------------
위에 예제에서, 주석 2) 에서 10 이라는 수를 10진수로 리터럴 상수로 이용했습니다. 조금 바꿔보면
var = 011; /* 2)값 대입 */
이라고 11 라는 숫자 앞에 0 하나를 붙여주세요. 그러면 결과로 뭐가 나오는 지 확인해 보세요.
결과는 9가 나옵니다. 왜, 이럴 까요. 앞에 0 이, 이 수는 8진수라고 알려줍니다. 그래서 8진수 9는 10진수로 9가 됩니다. 그래서 이러한 현상이 발생했습니다. 이제
var = 0x11; /* 2)값 대입 */
라고 하면 어떻게 될까요. 16진수 11은 10진수로 17이므로 17이 출력됩니다.
( 컴퓨터에서 기본적으로 모든 것이 2진수로 표현합니다. 2진수를 그냥 쓸 경우 긴 숫자단위가 필요합니다. 2진수로 255 라는 수를 표현하기 위해서는 8자리나 필요하게 됩니다. 그래서 이 2진수를 몇 자리씩 묶어 표현한니다. 3자리씩 묶으면 8진수로 표현할 수 있고, 4자리씩 묶으면 16진수로 표현 가능합니다.255 라는 10진수를 8진수로 표현하면 0377로 표현하고, 16표현하면 0xFF 입니다. )
그냥 정수형 리터럴 상수를 이용하면 숫자의 표현범위가 int 형과 같습니다. 그전의 16비트 컴퓨터 시스템에서는 int 형이 16비트 표현되었습니다. 이러다 보면 long 값이 4바이트인데 값을 대입하면서 값의 윗자리가 잘리는 경우가 있습니다. 이를 방지하기 위해 숫자 뒤에 L (소문자 l 도 가능, 그러나 숫자 1과 소문자 l 을 구별하는 게 좀 불편할 수 있으므로 대문자 L 을 추천합니다.) 이라는 값을 덧붙여 주었습니다. 요즘 컴파일러에서는 그렇게 큰 의미는 없겠지만 좀 안 좋은 환경에서 프로그래밍 하는 분을 이것을 고려해 주기 바랍니다.
long var = 0x12345678L
/* int 와 long 의 크기가 다른 경우 이렇게 long 인 것 표시한다./
이 부분은 굳이 이해할 필요없습니다. 모르겠으면 그냥 넘어가세요.*/
05.03 실수형 리터럴 상수
실수 (컴퓨터에서 실수라고 하면 소수(小數)점을 포함한 수입니다.)에 대해서는 오직 10진법만 사용됩니다. 수 앞에 0을 붙여도 그냥 10진수로 인식하고 0x 를 붙이면 오류를 발생합니다.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
double var; /* 1) */
var = 011.1; /* 2)값 대입 */
printf("%f \n", var); /* 3) */
system("PAUSE");
return 0;
}
----------------------------------------------------------------------------
출력은 그냥 11.1 입니다.
var = 0x11.1; /* 2)값 대입 */
라고 고치면 오류를 발생합니다.
실수형 리터럴 상수를 그냥 사용하면 double 형과 크기가 같습니다. 그래서 float 값을 사용하는데 문제가 생길 수 있습니다.
주석 1)대신
float var; /* 1) */
넣으면 경고가 생긴니다. ( visual c++6.0 에서는 나는데 Dev-cpp 에서는 그냥 컴파일 한다.) 경고가 생긴다고 컴파일이 안 되는 것은 아닙니다. 다만 별로 좋은 코드는 아닙니다. float 형임을 명시적으로 보여주기 위해서는 숫자 뒤에 f (또는 대문자 F도 가능합니다.) 를 붙입니다.
주석 2) 를
var = 011.1f; /* 2)값 대입 */
라고 고치는 게 좋습니다.
5.4 아스키코드 그리고 문자형 상수
앞 강의에서 문자형에서 문자 하나에 작은 따옴표를 붙이는 형식을 보았습니다. 이 방법으로 문자형 리터럴 상수를 만들 수 있습니다. 문자하나에(오직 문자 하나입니다.) ' ' (작은 따옴표) 를 붙이면 내부적으로 아스키코드로 인식합니다. 아스키코드는 문자를 컴퓨터로 저장할 수 있도록, 문자에 적당한 숫자를 부여한 규정입니다. 'a' 는 아스키코드 값 97을 갖습니다.
다음 예제에서 확인하세요.
----------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d \n", 'a');
system("PAUSE");
return 0;
}
----------------------------------------------------------------------------
이 예제는 97 이라는 값을 출력합니다. 만일 'a' 라는 표현방식으로 그 값의 아스키코드를 표시하지 못했다면 불편한 점이 많이 있었을 것입니다. a 를 출력하기 위해서는
printf("%c \n", 97); /* 여기서 %c 는 한 문자를 출력할 때 사용됩니다. */
라고 %c를 이용하면 됩니다.
우리는 굳이 이 아스키코드 값을 외울 필요가 없이 작은 따옴표로 문자를 감사 주기만 하면 됩니다.
따라서
printf("%c \n", 'a');
를 이용해서 a라는 문자를 출력할 수 있습니다.
( 안타깝게 한글은 '한' 이런 식으로 하면 에러가 납니다. 한글은 아스키코드 한 글자로 표현할 수 없습니다. 이럴 때는 어쩔 수 없이 문자열 상수를 이용해야 합니다. )
(여기서 문자라고 하는 것은 단순히 영문자 뿐만 아니라 숫자글자:0부터 9까지의 숫자, 기호:~, !, <,> 까지 포함하는 개념입니다.)
5.5 문자열(문자열 상수)
앞에서 토근의 구성요소 중 하나가 문자열이라고 말했습니다. 문자 하나에 대해서는 그냥 문자 상수라고 해서 상수에 포함시키는데 반해, 문자열의 경우는 하나의 토큰으로 취급하고 있습니다. 그 이유는 문자 상수의 끝은 '\0'( \ 가 (이 글꼴 시스템에서는 윈화(한국 돈의 단위)를 표시하는 기호로 나오군요. 이 글이 어떻게 나올지 모르겠지만, 역 슬래시라고 불리는 기호가 나오는 경우도 있습니다. 표시되는 모양은 달라도 컴파일러는 다 같은 것으로 인식하니 걱정 안하셔도 됩니다. )으로 끝나기 때문입니다. 이 이유는 조금 나중에 다시 설명하고 문자열 상수를 표시하기 위해서는 문자들에(문자 하나 이상을 의미합니다) "Hello" 처럼, 큰 따옴표로 감싸야 합니다. 이 경우 크기가 글자수는 5자인데, 그 저장공간은 6byte입니다. 영문자 하나가 1바이트라서 5글자라서 5byte가 되고 끝에 문자가 끝났다는 표시로 '\0' 가 들어갑니다. '\0' 는 널(Null) 문자라고 불립니다. (나중에 나올 NULL 이라는 기호와 구별하기 바랍니다. 이 NULL은 Null 포인터라고 불립니다.)
문자열을 배웠으니 문자열예제를 보여드리겠습니다. 근데 이 예제는 우리가 처음에 본적이 있는 예제입니다.
-------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
printf("Hello, world \n");
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
우리가 처음에 배웠던 Hello, world라는 글자를 찍는 예제입니다. 우리도 모르게 이미 문자열 찍는 방법을 배웠군요. 이제 저 Hello, world 라는 글자 끝에 있는 \n의 정체에 대해 배워봅시다.
-------------------------------------------------------------------------------
#include <stdio.h>
int main()
{
printf("Hello \n world!!");
printf("");
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
Hello
world!!계속하려면 아무 키나 누르십시오 . . .
------------------------------------------------------------------------
감을 잡으셨을 거라는 생각이 듭니다. \n은 글을 다음 줄로 내리는 효과를 발생시킵니다.
\ 가 들어 가는 문을 escape 문자라고 부릅니다. 약간의 특별한 역할을 하는 문자라고 생각하면됩니다.
이스케이프 문자에는 다음과 같은게 있습니다.
\' : 작은 따옴표를 표시합니다.
\" : 큰 따옴표를 표시합니다.
\\ : 문자 \ 를 표시합니다.
\t : 탭을 사용한 효과를 냅니디.
\n : 글을 다음줄로 보냅니다. 텍스트에디터에서 엔터친 효과와 비슷하죠.
\b : backspace 를 누른 것과 같은 효과를 냅니다. 앞의 글을 지웁니다.
\a : beep 음을 냅니다. 컴퓨터에서 삐 ~ 소리 냅 것 들은 적 있죠. 정말, 예전
컴퓨터 스타일로 냅니다. 조심하시길, 조금 귀에 거슬려서..
\n 대신에 다른 것을 넣어 실험해 보세요.
5.6 const 를 이용한 기호상수
우리가 앞서 배웠던 변수를 선언하는 방식에서 const 만 앞에 붙이면 기호상수를 선언 할 수 있습니다.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int var = 11 ;
printf("%d \n", var);
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
이제 상수 var 는 변수처럼 여러 번 대입 할 수 없습니다. 숫자 11 로 고정되는 것입니다.
다음 예제는 컴파일되지 않습니다. var = 22 에서 오류가 발생한다고 error가 나옵니다.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int var = 11 ; /* 1) */
var = 22;
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
위의 예제에서 주석 1) 에서 const 만 빼버린다면 변수이므로 에러 없이 컴파일 할 수 있습니다.
그래서 다음과 같은 것도 안됩니다.
----------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const int var;
var = 11; /* 1) */
system("PAUSE");
return 0;
}
-------------------------------------------
주석 1)에서 error가 발생합니다. 그래서 선언과 동시에 초기화를 해야 합니다.
const int var;
var = 11;
를
const int var = 1;
로 할 수 있습니다.
const를 이용한 기호상수는 한 번 정의하고나 다른 값을 대입할 수 없으므로 선언함께 초기화를 해야 합니다.
왜, 이런 기호상수를 이용할 까요.
다음 예제를 보세요.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
int main()
{
const double PI = 3.1415926535897932384626 ; /* 1) */
printf("%f\n", PI );
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
수학에서 사용하는 PI 같은 연산을 절대로 변할 수 없는 수입니다. 이런 PI 대신 리터럴 수로 직접 숫자를 쓴다고 해보세요. 얼마나 불편하겠습니까. PI의 경우 사람들이 많이 아는 상수이므로 큰 문제가 없겠지만 프로그램 안에서만 사용하는 특별하게 사용하는 숫자는 그 용도를 모르는 경우가 많겠지요. 그래서 그 용도까지 분명히 하면서 프로그래밍을 할 수 있도록 도와 주는 게 기호상수 입니다.
5.7 #define 문
# 가 들어가는 문은 전처리기에서 처리한다고 말한 적 있습니다. 이 전처리기가 무엇인지는 나중에 자세히 설명하겠습니다. 이 전처리기를 이용해서 상수를 표현하는 방법에 대해 예제만 보여주겠습니다.
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define PI 3.1415926535897932384626
int main()
{
printf("%f\n", PI );
system("PAUSE");
return 0;
}
-------------------------------------------------------------------------------
5.6 에서 설명한 예제를 조금 고쳤습니다. 이에 대한 설명은 나중에 합시다. 지금 이 글을 읽는 사람은 안 그래도 엄청나게 머리 아플 테니까.
다시 한 번 정리하겠습니다. 아직 리터럴 상수와 상수, 변수가 혼동할 것 같군요. (#define 에 대해서는 나중에 다시 배울테니 잠시 잊어 두셔요. )
우선 리터럴 상수는 숫자와 문자 그대로를 이용한 것 입니다. 문자 리터널 상수는 작은 따옴표나 큰 따옴표로 묶여 있습니다. 변수는 앞 강의에서 설명한 심볼로 이루어져 있습니다. 그리고 리터럴 상수를 이용해 초기화 합니다. 상수는 변수는 선언하는 방식으로 하되, 앞에 const 를 붙여 줍니다.
리터럴 상수는 처음이 작은 따옴표나 큰 따옴표 또는 숫자로 시작합니다. ( 16진수나 8진수를 표기 할 때도 0x 나 0 같이 숫자 0으로 시작합니다.) 그래서 리터럴 상수와 다른 것을 혼돈할 일은 없습니다. 그런데 const 를 이용한 상수와 변수는 오직 프로그래밍 짜는 사람들 마음대로 이름을 정하다 보니 혼돌될 염려가 있습니다. 그래서 여기에 보이지 않는 규칙이 하나 있습니다. const 를 이용한 상수를 대문자로 시작하는 것 입니다.
참고 사항
#1 8,16진수 표현에 대하여.
10진수를 표현하기 위해서는 10개의 기호가 필요합니다. 보통 우리는 아라비아 숫자를 사용합니다. 16진수를 표기하기 위해서는 6개의 숫자가 더 필요합니다. 컴퓨터에서는 보통 A, B, C, D, E (소문자로 표현해도 됩니다.) 까지의 알파벳을 이용합니다. C언어 형식을 따른다면 0xA는 십진수로 10을 나타내고, 0xB는 십진수 11,
0xF 는 십진수로 15 입니다.
2진수를 8진수, 16진수로 표현하기 쉽습니다. 그 역도 쉽습니다.
잠시 초점을 10진수에 맞추어 봅시다. 10진수를 1000 진수로 변환한다고 하고, 그 기호는 (xxx)식으로 괄호를 묶어 표현 해 보겠습니다.
1234578 이라는 수를 1000 진수로 표현하면 (1234)(5678) 입니다. 너무 당연하지 않습니까.
2진수와 8진수,16진수 관계도 이러합니다. 2진수를 8진수로 표현하기 위해서는 3자리씩 묶어 표현하고, 16진수로 표현하기 위해서는 4자리씩 묶어 표현하면 쉽습니다.
2진수 11101100 을 8진수로 표현하기 위해서는 (11)(101)(100)이런 식으로 뒤에서 3자리씩 묶고, 괄호 안의 수를 8진수로 표현하면, 8진수354 가 됩니다. 16진수로 표현하려면 (1110)(1100) 으로 묶으면 16진수 EC라고 표현할 수 있습니다.
#2 Lvalue 와 Rvalue
Lvalue : 왼쪽값[조금 이상하군요] 좌변값이라고 부르기도 합니다.
Rvalue : 우변값이라고 부르기도 합니다.
덧 글(덧붙이는 글)
너무 조급한 마음 가지지 마세요. 내가 일주일만에 C 를 완벽히 정복한다. 이런 마음은 안 가지시는 게 좋습니다. 완벽 정복은 시일이 많이 걸릴 수밖에 없습니다. 그 전에 말씀드렸다시피 프로그래밍 언어를 배우다 보면 필연적으로 컴퓨터 구조나, 알고리즘 등등이 필요합니다. 그래서 빠른 시일 안에 배우기 어렵습니다. 다만 자주 사용하는 내용은 빠른 시일에 배울 수 있습니다. 그래서 제 글에는 어려운 부분을 많이 빼두고 진행할 계획입니다. 그 부분은 잘 사용하면 알차게 프로그래밍 할 수는 있지만, 배우는 사람의 입장에서는 흥미를 잃기 쉽습니다. 좀 부족하더라도 전체 흐름을 읽는 게 중요하다고 생각합니다.
작성자 : 한밀(승룡)
버전 : 0.1.5
이 글은 계속 고쳐지고 있습니다.
2003년 12월 어느 추운 날
최종 수정일 : 2008년 2월 말, 2월인데 아직 눈이 내리다니..

Literal 상수와 기호 상수를 구별했는데, 예전 C책에 이런 방식을 많이 사용하길래, 따라 했는데, 이게 적당한지 알 수 없군요..