' [C/C++] 7강 - 상수, C언어에서 상수 사용하기 (1) (const,#define)

Programming/C & C++

[C/C++] 7강 - 상수, C언어에서 상수 사용하기 (1) (const,#define)

mdisprgm 2021. 6. 20. 14:11
728x90

(1) 상수란

프로그램에는 '변수'라는 것이 있다.

 

변수는 값을 저장하기 위해 할당된 메모리로

 

그 값이 언제든 변경될 수 있는 특성이 있다.

 

 

 그러나 그 값이 절대 바뀌어서는 안 되는 경우들도 있는데,

 

원주율, 파이(\(\pi\)) 나, 

 

국제 단위계서 질량의 표준을 규정하는 새 기준 플랑크 상수 등등 말이다.

 

이러한 것들은 절대 변해서는 안 되는 수들이다.

 

이러한 상수들을 관리할 때 그냥 프로그래머가 = 연산자를 쓰지 않기로만 약속한다면

 

언제 실수가 있을지 모르니 불안하기도 하고

 

디버깅을 할 때도 고려해야할 문제가 더 생긴다.

 

그래서 프로그래밍 언어에서는 언어적 차원에서 상수에는 값을 변경시킬 수 없도록 하는 문법이 존재하는데

 

이 포스팅에서는 C에서 그러한 상수 문법을 살펴볼 것이다.

 

(2) 상수를 사용하기

프로그램에 \(\pi\)의 값이 필요할 때는 매번 3.141592... 를 적는 것보다 변수에 저장해서 사용하는 게 훨씬 쓰기가 편하다.

float PI = 3.141592;

 

그런데 여기엔 중요한 문제가 있는데

 

위에서 말했듯이 변수는 언제든 값이 바뀔 수 있다는 것이다.

 

좀 극단적인 예시를 들어보자면

/* ... Some codes ...*/

float PI = 3.141592;

/* ... Some codes ...*/

PI = 5;

/* ... Some codes ... */

이런 코드를 생각해보자.

 

프로그래머가 PI = 5;라는 어이없는 실수를 해서 PI가 5가 된다면

 

이후에 PI를 사용하는 코드들은 모두 엉망이 될 것이다.

 

이런 상황을 방지하기 위해서 만들어진 것이 계속 말하는 '상수'이다.

 

상수를 사용하는 방법엔 여러가지가 있는데

 

 

ㄱ) 상수를 의미하는 constant의 const를 자료형 앞에 붙여 const 상수로 선언하면 된다.

 

이렇게 const로 정의된 상수를 기호 상수라고 한다.

const float PI = 3.141592;

이렇게 하면  더 이상 PI = 5; 와 같은 식을 사용할 수 없다.

 

PI라는 변수는 const화 되었기 때문이다.

 

이 코드를 포함해 컴파일을 시도한다면 에러가 발생한다.

 

"const인 변수에 할당할 수 없습니다"

 

 

ㄴ) 두 번째 방법은 #define이라는 것인데, #include처럼 #이 붙은 전처리기이고, '매크로'라고도 한다.

 

매크로를 지원하는 언어는 소스코드 차원에서 간단한 언어 '확장'이 가능해진다.

이런 걸 우스갯소리로 매크로 흑마법이라고도 한다는..ㅋㅋ

 

 

전처리기란 최종 코드를 실행 파일로 번역하기 전에 미리 처리하는 작업들이라고 했다.

 

그중 #define은 매크로를 정의할 수 있는데, 사용법은 간단하다

 

#define (매크로 이름) (값)

#define PI 3.141592
//관례적으로 상수의 이름은 모두 대문자로 작성합니다

int main() {
	const double vPI = PI;
}
//#include는 헤더 파일의 모든 내용을 복사하는 전처리기라 출력되는 결과의 내용이 너무 길어져 생략합니다
//따라서 printf도 사용할 수 없습니다

이렇게 하면 해당 소스코드 파일에서 PI 는 모두 3.141592로 '치환'되어 작동하며

 

다른 용도로는 (문자열 리터럴 제외) PI라는 이름을 절대 사용할 수 없다.

 

이 치환된다는 게 무엇이냐면, 말그대로 코드 내에서 PI 라는 문자열이 3.141592 대체된다.

 

이것에 define 전처리기의 역할이다. 매크로 이름이 사용된 곳을 지정된 값으로 치환하는 것!

 

백문이불여일견

 

gcc라는 컴파일러에서 -E 옵션을 사용하면 전처리기만 일차적으로 처리한 결과를 볼 수 있다.

 

 

위 코드를 그대로 적용한 모습이다.

 

 

const double vPI = PI; 의 PI가 3.141592로 치환된 걸 볼 수 있다. 이렇게 모든 전처리기가 처리된 후 실행 파일로 컴파일 되는 것이다.

 

 

ㄷ) 사실 3.141592도 상수이다. 왜? 일단 3.141592 가 변수는 아니다.

 

따라서 3.141592는 변할 수 없으며

 

int 3.141592 = 100; 이런 코드가 불가능하다는 건 이미 모두가 알고 있는 사실이다.

 

이러한 숫자 자체를 '리터럴 상수'라고 합니다. (literal)

 

 

(3) l-value와 r-value

C/C++에서 여러 값들은 크게 두 가지 종류로 나뉠 수 있는데

 

바로 l-valuer-value입니다. 각각 left-side-value, right-side-value 라는 의미인데

 

등호(=)를 기준으로 왼쪽에 둘 수 있으면 l-value이고 오른쪽에만 둘 수 있으면 r-value이다.

 

여기서 주의해야할 것은 l-value들도 오른쪽에 둘 수 있다.

 

다만, 오른쪽에"" 둘 수 있을 뿐이다.

 

이런 것들은 l-value라고 한다.

 

그러나

 

3.141592 같은 리터럴이나 PI같은 상수는

 

오른쪽에"" 올 수 있기 때문에 r-value에 속한다.

//이것은 상수가 아니다
//따라서 이는 l-value이다.
double PI_1 = 3.141592;
//PI_1 = 3.1415; 이러한 식이 허용된다는 얘기다.

//그러나 이것은 상수이다.
//따라서 이는 r-value이다.
const double PI_2 = 3.141592;
//PI_2 = 3.1415; 이러한 식이 허용되지 않는다는 얘기다.

 

 

다음 강좌에서는 상수를 표현하는 또 다른 방법인 enum에 대해 포스팅한다.

 

 

끝.

 

 

728x90

'