상수와 리터럴
지난 편에서는 값이 자유롭게 바뀔 수 있는 “변수”에 대해 배웠습니다. 그런데 프로그램을 짜다 보면 절대 바뀌면 안 되는 값도 있습니다. 예를 들어 원주율이나 세율처럼 계산 도중에 실수로 값이 바뀌면 프로그램 전체가 엉망이 될 수 있는 값들이죠. 오늘은 이런 “바뀌지 않는 값”인 상수(constant)와, 코드에 직접 써넣는 값인 리터럴(literal)에 대해 알아보겠습니다.
리터럴이란?
리터럴은 코드 안에 그 자체로 적혀 있는 값을 말합니다. 예를 들어 아래 코드에서 10, 3.14, 'A', "hello"는 모두 리터럴입니다.
int x = 10; // 정수 리터럴
double pi = 3.14; // 실수 리터럴
char grade = 'A'; // 문자 리터럴
char *msg = "hello"; // 문자열 리터럴
리터럴에도 자료형이 있습니다. 10은 기본적으로 int, 3.14는 기본적으로 double로 취급됩니다. 만약 정수 리터럴을 long으로, 실수 리터럴을 float로 명시하고 싶다면 접미사를 붙일 수 있습니다.
long big = 1000000L; // L을 붙이면 long 타입
float f = 3.14f; // f를 붙이면 float 타입
unsigned int u = 10U; // U를 붙이면 unsigned int 타입
또한 정수 리터럴은 진법도 다르게 표현할 수 있습니다. 0x로 시작하면 16진수, 0으로 시작하면 8진수로 해석됩니다.
int decimal = 100; // 10진수
int hex = 0x64; // 16진수(100과 같은 값)
int octal = 0144; // 8진수(100과 같은 값)
상수란?
상수는 변수처럼 이름을 가지지만, 한 번 값이 정해지면 프로그램이 실행되는 동안 절대 바뀌지 않는 값입니다. C언어에서 상수를 만드는 방법은 크게 두 가지가 있습니다.
첫 번째는 const 키워드를 사용하는 방법입니다. 변수 선언 앞에 const를 붙이면 그 변수는 이후 값을 변경할 수 없는 상수가 됩니다.
const double PI = 3.14159;
두 번째는 전처리기 지시문인 #define을 사용하는 방법입니다. 이는 컴파일 전에 코드에서 해당 이름을 지정된 값으로 그대로 바꿔치기하는 방식입니다.
#define MAX_SCORE 100
두 방식 모두 비슷한 목적으로 쓰이지만, const는 자료형이 명확하게 지정되고 디버깅 시 변수처럼 취급되는 반면, #define은 단순 텍스트 치환이라 자료형이 없다는 차이가 있습니다. 요즘은 안전성 때문에 const를 더 권장하는 편입니다.
예제 코드로 확인해보기
아래는 상수와 리터럴을 함께 사용해 원의 넓이와 둘레를 계산하는 예제입니다.
#include <stdio.h>
#define MAX_RADIUS 1000
int main(void) {
const double PI = 3.14159;
double radius = 5.0;
if (radius > MAX_RADIUS) {
printf("반지름이 너무 큽니다.\n");
return 1;
}
double area = PI * radius * radius;
double circumference = 2 * PI * radius;
printf("반지름: %.1f\n", radius);
printf("넓이: %.2f\n", area);
printf("둘레: %.2f\n", circumference);
// PI = 3.14; // 이 줄의 주석을 풀면 컴파일 에러가 발생합니다.
return 0;
}
코드 동작 설명 및 실행 결과
#define MAX_RADIUS 1000은 전처리기가 컴파일 전에 코드 안의MAX_RADIUS를 전부1000이라는 텍스트로 바꿔치기합니다. 그래서radius > MAX_RADIUS는 실제로는radius > 1000으로 컴파일됩니다.const double PI = 3.14159;는PI라는 이름의 상수를 선언한 것입니다. 이후 코드에서PI = 3.14;처럼 값을 바꾸려고 하면 컴파일러가 “읽기 전용 변수에 값을 대입할 수 없다”는 에러를 냅니다.area와circumference는 각각 원의 넓이(반지름² × PI)와 둘레(2 × PI × 반지름) 공식으로 계산됩니다.%.2f는 소수점 아래 2자리까지 출력하라는 서식 지정자입니다.
이 코드를 gcc constants.c -o constants로 컴파일하고 실행하면 다음과 같은 결과를 볼 수 있습니다.
반지름: 5.0
넓이: 78.54
둘레: 31.42
만약 주석 처리된 PI = 3.14; 줄의 주석을 풀고 다시 컴파일하면, “assignment of read-only variable ‘PI’“와 같은 컴파일 에러가 발생합니다. 이것이 바로 상수가 우리를 지켜주는 방식입니다. 값을 실수로 바꾸는 코드를 아예 컴파일 단계에서 막아주는 것이죠.
핵심 요약
- 리터럴은 코드에 직접 적혀 있는 값이며, 정수·실수·문자·문자열 등 다양한 종류가 있고 접미사(
L,f,U)로 자료형을 명시할 수 있습니다. - 상수는 한 번 정해지면 바뀌지 않는 값으로,
const키워드나#define전처리기 지시문으로 만들 수 있습니다. const는 자료형이 있는 진짜 변수처럼 취급되고,#define은 컴파일 전 단순 텍스트 치환이라는 차이가 있습니다.- 자주 바뀌면 안 되는 값(원주율, 최대값, 세율 등)은 상수로 선언해두면 실수를 방지하고 코드의 의도도 더 명확해집니다.
다음 편에서는 값을 계산하고 비교하는 데 꼭 필요한 “연산자 (산술/관계/논리/비트)”에 대해 알아보겠습니다. C언어에서 자주 쓰는 다양한 연산자의 종류와 사용법을 예제와 함께 정리해보겠습니다.