코딩 노트

05-3 상수에 대한 이해 본문

C

05-3 상수에 대한 이해

newbyeol 2021. 5. 5. 20:15

변수의 상대적 개념인 상수에 대해서 알아보자. 상수는 크게 이름이 있는 상수와 이름이 없는 상수로 나뉘며, 상수 역시 앞서 설명한 int, double과 같은 자료형을 근거로 표현이 된다. 그리고 이러한 사실을 이해하는 것은 매우 중요하다.

1. 이름을 지니지 않은 리터럴 (Literal) 상수

상수란, 그 이름이 의미하듯이 변경이 불가능한 데이터를 뜻한다. 위 코드에는 30과 40의 합의 결과를 변수 num에 저장하는 문장이 존재한다. 그렇다면 대입연산과 덧셈연산중에 무엇이 우선이겠는가? 당연이 30 + 40 덧셈연산이 우선이다. 즉, 덧셈이 우선 진행되고, 그 결과로 얻어진 값으로 변수 num을 초기화하게 된다. 그렇다는 것은 30+40의 연산을 CPU가 진행해야 한다는 뜻인데, 그러기 위해서는 30이라는 정수도, 40이라는 정수도 메모리상에 존재해야 한다. 그래야 CPU의 연산대상이 될 수 있기 때문이다. 메모리에 존재하지도 않는 값을 대상으로 덧셈연산이 가능이나 하곘는가?

 

상수의 특징 하나는 변수 num과 달리 할당된 메모리 공간에 이름이 없다는 것이다. 이렇듯 변수와 달리 이름이 없는 상수를 가리켜 '리터럴 상수'또는 그냥 '리터럴'이라고 한다. 그럼 다음 코드를 보면서, 실행과정에서 메모리 공간에 할당되는 변수와 상수의 수가(리터럴의 수가)몇 개 인지 세어보자.

int main(void)
{
	int num1 = 3 + 4;
	int num2 = 7 + num1;
	double num3 = 2.12 + 7.49
	. . . .
}

변수의 수는 num1,  num2, num3 이렇게 총 3개이고, 상수의 수는 정수형 상수와 실수형 상수 모두 포함해서 3, 4, 7, 2.12, 7.49 이렇게 총 5개이다.

2. 리터럴 상수의 자료형

자료형은 변수만을 위해서 존재하는 것이 아니다. 자료형은 상수를 위해서도 존재한다. 상수를 메모리 공간에 저장하려면 실수의 형태로 저장해야 하는지 아님 정수의 형태로 저장해야 하는지, 몇 바이트의 크키로 저장해야 하는지... 즉 어떠한 자료형으로 저장해야 하는지 고민이 될 수 있다.

 

메모리상에 저장되는 모든 데이터는 자료형이 결정 되어야 하는데 그래야 저장하는 방법이 정해지기 때문이다.

int main(void)
{
	int inum = 5; // 정수형 상수
	double dnum = 7.15; // 실수형 상수
	. . . .
}

위 코드의 세 번째 행에 등장하는 상수 5와 같이 int형으로 표현 가능한 정수형 상수는 int형으로 메모리 공간에 저장하기로 약속되어 있다. 물론 int로 표현이 불가능한 크기의 정수는 그보다 큰 자료형의 정수로 표현이 된다. 그리고 네 번째 행에 등장하는 상수 7.15와 같이 double형으로 표현 가능한 실수형 상수는 double형으로 저장하기로 약속되어 있다. 그런데 오해하면 안 될 것이 있는데, 대입 연산자의 왼편에 있는 변수의 자료형에 따라서 상수의 자료형이 결정되는 것은 아니다. 다만, 대입 연산자의 오른편에 선언된 상수의 자료형에 어울리게 변수의 자료형을 선언했을 뿐이다.

 

char ch = 'A';

 

이 문장에서 보이는 문자(문자형 상수)는 어떻게 표현될까? char형으로 표현된다고 생각하겠지만 위의 문장은 컴파일러에 의해 다음과 같이

 

char ch = 65;

 

로 바뀐다. 그리고 65는 정수이니, 4바이트 크기의 int형으로 표현되어야 한다. sizeof 연산자를 이용해서 리터럴 상수의 크기를 확인해볼 수 있다. 그 결과로 문자형 상수의 크키가, int형의 크기인 4바이트로 표현됨을 확인하였다.

3. 접미사를 이용한 다양한 상수의 표현

정수형에는 int만 있는 게 아니고, 실수형에는 double만 있는 게 아니다. 그 이외의 자료형을 기반으로 상수를 표현하려면 해당 자료형을 의미하는 접미사를 붙여주면 된다.

int main(void)
{
	float  num1 = 5.789; //경고 메시지 발생
	float num = 3.24 + 5.12 // 경고 메시지 발생
	return 0;
}

위의 코드는 컴파일 가능하지만, 초기화할 때, double형 데이터를 float형 변수에 저장하였으니, 데이터가 잘려나갈 수도 있다고 경고 메시지가 뜬다. 5.789는 8바이트 크기의 double형 상수이고, 변수 num1은 4바이트 크기의 float형 변수이므로, 이러한 경고 메시지가 뜨는 것이 당연하다. 그렇다면 float형 상수를 float형 변수에 저장하려면 어떻게 해야할까?

다음과 같이 float형을 의미하는 f를 상수의 뒤에 붙여주면 된다.

참고로 위의 접미사들은 대소문자를 구분하지 않으므로 눈에 잘 띄도록 상황에 맞게 대소문자를 선택하면 된다.

4. 이름을 지니는 심볼릭(Symbolic) 상수: const 상수

심볼릭 상수는 변수와 마찬가지로 이름을 지니는 상수이다. 이러한 심볼릭 상수를 표현하는 방법에는 두 가지가 있는데, 그 중 하나는 'const 키워드'를 사용하는 방법이고, 또 하나는 매크로를 이용하는 방법인데 const 키워드를 사용하는 방법만 먼저 언급하겠다. 

 

const 키워드를 이용해서 상수를 만드는 방법은 변수 선언 시 const 선언만 추가하면 된다. 단, 이는 상수이므로 선언과 동시에 초기화를 해야 한다.

int main(void)
	const int MAX=100; // MAX는 상수! 따라서 값의 변경 불가!
	const double PI=3.1415; // PI는 상수! 따라서 값의 변경 불가!
	. . . .
}

위의 main 함수 내에서는 MAX라는 이름의 상수와 PI라는 이름의 상수를 선언하고 있다. 이처럼 이름을 지니는 상수를 가리켜 심볼릭 상수라 한다. 심볼릭 상수도 상수의 일종이므로, 일단 초기화되면 그 값을 변경시킬 수 없다. 뿐만 아니라, 다음과 같이 선언과 초기화를 분리시킬 수도 없다.

int main(void)
	const int MAX; // 쓰레기 값으로 초기화 되어버림
	MAX=100; // 값의 변경 불가! 따라서 컴파일 에러 발생!
	. . . .
}

const 상수도 일반 변수와 마찬가지로 선언만 하고 초기화를 하지 않으면 쓰레기 값으로 초기화되어 이후에 값을 변경하려 들 떄 컴파일 에러가 발생한다. 참고로 상수의 이름은 모두 대문자로 표시하고, 둘 이상의 단어로 연결할 때에는 MY_AGE와 같이 언더바를 이용해서 두 단어를 구분하는 것이 관례라는 걸 기억해야한다. 이는 변수와 상수의 구분을 용이하게 하는데 목적이 있는 관례이다.

'C' 카테고리의 다른 글

06-1 printf 함수 이야기  (0) 2021.05.06
05-4 자료형의 변환  (0) 2021.05.06
05-2 문자의 표현방식과 문자를 위한 자료형  (0) 2021.05.05
05-1 C언어가 제공하는 기본 자료형의 이해  (0) 2021.03.05
04-3 비트 연산자  (0) 2021.02.19