C언어 변수 (자료형, 형변환, 저장클래스)
C언어를 배우는 모든 사람이 가장 먼저 마주치는 두 개념이 바로 변수(Variable)와 데이터 타입(Data Type)이다. 이 두 개념을 정확히 이해하지 못하면 그 어떤 복잡한 알고리즘도 올바르게 구현할 수 없으며, 메모리 관리·포인터·구조체 같은 후속 개념도 무너진 토대 위에 쌓이는 셈이 된다. C언어가 자료형에 매우 엄격한 정적 타입 언어인 만큼, 변수의 선언 방식과 자료형의 크기·범위를 명확히 알고 있어야 안정적인 프로그램을 작성할 수 있다(출처: ISO C 표준 — cppreference). 본 글은 C언어 입문자가 반드시 갖춰야 할 변수의 개념과 명명 규칙, 기본 데이터 타입의 크기와 범위, 그리고 타입 변환과 저장 클래스를 한 번에 정리한다. 제가 학교 C언어 수업 첫 주차에 가장 헛갈렸던 게 char가 사실은 정수형이라는 사실이었는데, 'A' + 1이 'B'를 만들어 내는 한 줄 실험을 직접 돌려 본 후로는 자료형이 단순한 명패가 아니라 메모리 해석 방식이라는 점을 손끝으로 받아들였다.

변수의 개념과 명명 규칙
변수란 데이터를 저장하기 위한 메모리 공간에 이름을 붙인 것을 의미한다. 컴퓨터의 메모리는 본질적으로 0과 1의 비트 배열이지만, 프로그램이 매번 비트 단위로 데이터를 다루는 것은 사실상 불가능하기 때문에 일정한 크기의 메모리 영역에 의미 있는 이름을 부여하고 그 이름으로 데이터에 접근하는 방식을 사용한다. C언어에서 변수를 만드는 작업은 두 단계로 이루어진다. 첫째는 선언(Declaration)으로, 자료형 변수명; 형식으로 작성해 컴파일러에게 어떤 종류의 데이터가 어떤 이름의 메모리 공간에 저장될 것인지를 알려준다. 둘째는 초기화(Initialization)로, 자료형 변수명 = 초기값; 형식으로 변수를 만들면서 동시에 값을 할당한다. 여기서 쓰레기 값(Garbage Value)이란 메모리 공간을 확보만 하고 초기화하지 않았을 때 그 자리에 남아 있던 임의의 비트 패턴이 의미 없는 값으로 해석되는 현상을 가리킨다. 초기화하지 않은 지역 변수는 쓰레기 값을 가지므로, 사용 전에 반드시 의미 있는 값으로 초기화하는 것이 안전한 코딩의 첫 번째 원칙이다.
변수 이름을 정할 때는 C언어의 식별자(Identifier) 명명 규칙을 반드시 지켜야 한다. 첫째, 영문 알파벳, 숫자, 언더스코어(_)만 사용할 수 있다. 둘째, 이름의 첫 글자는 영문 알파벳 또는 언더스코어여야 하며, 숫자로 시작할 수 없다. 셋째, 대소문자를 구분하므로 age와 Age는 서로 다른 변수로 인식된다. 넷째, int·return·while 같은 C언어의 예약어(Keyword)는 변수 이름으로 사용할 수 없다. 다섯째, 이름의 길이에는 컴파일러별로 차이가 있지만, 일반적으로 31자 이내로 짓는 것이 안전하다.
변수 명명에서 규칙을 지키는 것 못지않게 중요한 것이 가독성을 높이는 작명 관습이다. 한 글자짜리 이름인 i·j·k는 반복문 카운터 같은 짧은 범위에서만 사용하고, 그 외에는 변수가 무엇을 담고 있는지 한눈에 알 수 있는 이름을 사용해야 한다. 예를 들어 학생의 점수를 담는 변수는 a보다 score 또는 student_score로 짓는 것이 훨씬 좋은 코드이다. 명명 스타일은 크게 세 가지가 있는데, 단어를 언더스코어로 잇는 스네이크 케이스(snake_case), 첫 단어 외에는 대문자로 시작하는 카멜 케이스(camelCase), 모든 단어를 대문자로 시작하는 파스칼 케이스(PascalCase)이다. C언어 진영에서는 전통적으로 스네이크 케이스가 가장 널리 사용된다.
C언어 기본 데이터 타입과 크기
C언어의 기본 데이터 타입은 표현하려는 값의 종류에 따라 정수형, 실수형, 문자형으로 분류된다. 각 타입은 메모리에서 차지하는 크기가 다르며, 따라서 표현할 수 있는 값의 범위도 달라진다. 시험과 실무 모두에서 자주 묻는 영역이므로 각 타입의 크기와 범위를 정확히 외워두어야 한다. 다만 자료형의 크기는 운영체제와 컴파일러에 따라 미묘하게 다를 수 있기 때문에, 정확한 크기는 sizeof 연산자를 사용해 확인하는 습관을 들여야 한다.
| 분류 | 자료형 | 크기 (일반적) | 범위/특징 |
|---|---|---|---|
| 정수형 | char |
1바이트 | -128 ~ 127 |
| 정수형 | short |
2바이트 | -32,768 ~ 32,767 |
| 정수형 | int |
4바이트 | 약 -21억 ~ +21억 |
| 정수형 | long |
4/8바이트 | OS·컴파일러 의존 |
| 정수형 | long long |
8바이트 | 약 ±9.2×10¹⁸ |
| 실수형 | float |
4바이트 | 유효자릿수 약 7 |
| 실수형 | double |
8바이트 | 유효자릿수 약 15 |
| 문자형 | char |
1바이트 | ASCII 정수형 |
정수형 앞에 unsigned 키워드를 붙이면 음수를 표현하지 않는 대신 양수 범위가 두 배로 확장되며, signed는 부호를 명시하는 키워드로 생략할 수 있다. 실수형은 IEEE 754 부동소수점 표준에 따라 부호·지수·가수 세 부분으로 비트가 나뉜다. 여기서 IEEE 754란 컴퓨터가 실수를 비트로 표현하기 위해 국제 전기전자공학회가 표준화한 부동소수점 형식 규약을 의미한다. 부동소수점은 본질적으로 근사값이기 때문에 0.1 + 0.2가 정확히 0.3이 되지 않는다는 점을 항상 기억해야 한다.
문자형은 단일 문자를 표현하는 자료형으로 char가 사용되지만, 내부적으로는 ASCII 코드값을 저장하는 1바이트 정수형이라는 사실에 유의해야 한다. 'A'는 65, 'a'는 97, '0'은 48 같은 정수로 저장되며, 따라서 'A' + 1을 계산하면 'B'에 해당하는 66이 된다. 문자열은 char 자료형의 배열로 표현하며, 끝을 알리는 NULL 문자(\0)로 종료된다.
실기 빈출 예제 — 자료형과 형변환
정보처리기사 실기에서 자주 출제되는 형식이 "다음 C 코드의 출력 결과를 쓰시오" 유형이다. 자료형의 크기와 형변환을 동시에 묻는 대표 예제를 풀어 보자(출처: K&R The C Programming Language, 2nd ed.).
#include <stdio.h>
int main(void) {
int a = 7;
int b = 2;
float c = (float)a / b; // 명시적 형변환
float d = a / b; // 정수 나눗셈 후 형변환
char ch = 'A';
printf("%.2f\n", c); // 3.50
printf("%.2f\n", d); // 3.00 (정수 나눗셈 결과 3을 float로 변환)
printf("%d\n", ch + 1); // 66
return 0;
}
출력 결과는 3.50, 3.00, 66이다. 핵심 포인트는 두 가지다. 첫째, (float)a / b는 a를 먼저 float로 변환한 뒤 나누기 때문에 결과가 정확한 3.5가 되지만, a / b는 정수끼리 나눠 3을 만든 뒤 float로 담기 때문에 3.0이 된다. 둘째, char는 정수형이므로 ch + 1은 자동으로 int로 승격되어 65 + 1 = 66이 출력된다. 솔직히 제 경험상 실기에서 가장 자주 실수했던 게 정확히 이 정수 나눗셈 사고였고, 한 번 시험에서 틀린 후로는 "실수가 필요하면 피연산자 중 하나라도 실수형이어야 한다"는 한 줄을 항상 의식하는 습관이 자리 잡았다.
서로 다른 데이터 타입의 값이 함께 사용될 때는 자동 또는 수동으로 타입 변환(Type Casting)이 일어난다. 자동 형변환(Implicit Casting)은 컴파일러가 알아서 처리하는 변환으로, 일반적으로 데이터 손실이 없는 방향으로 진행된다. 강제 형변환(Explicit Casting)은 프로그래머가 직접 명시하는 변환으로, (자료형)값 형식으로 작성한다. (int)3.14는 3.14를 int로 강제 변환해 3을 만들고, 이 과정에서 소수점 이하 부분이 잘려나간다.
타입 변환과 저장 클래스
변수의 또 다른 중요한 속성은 저장 클래스(Storage Class)이다. 저장 클래스는 변수가 어디에 저장되고 얼마 동안 유지되며 어디서 접근 가능한지를 결정하는 속성으로, C언어에는 네 가지 저장 클래스 키워드가 존재한다.
| 키워드 | 저장 영역 | 생존 기간 | 사용처 |
|---|---|---|---|
auto |
스택 | 함수 호출 동안 | 지역 변수 기본값 (생략 가능) |
static |
데이터 영역 | 프로그램 종료까지 | 값 유지·파일 범위 제한 |
extern |
데이터 영역 | 프로그램 종료까지 | 다른 파일 전역 변수 참조 |
register |
CPU 레지스터(권장) | 함수 호출 동안 | 현대 컴파일러에서 사실상 무시 |
여기서 정적 변수(static)란 한 번 만들어지면 프로그램이 끝날 때까지 사라지지 않고 메모리에 남아 있는 변수를 가리키며, 함수 안에 선언해도 호출 사이에 값이 유지된다는 결정적 차이를 가진다. 다음 코드는 정적 변수가 호출 사이에 값을 유지하는 모습을 보여 주는 시험 빈출 패턴이다.
#include <stdio.h>
void counter(void) {
static int n = 0; // 프로그램 시작 시 한 번만 0으로 초기화
n++;
printf("호출 횟수: %d\n", n);
}
int main(void) {
counter(); // 호출 횟수: 1
counter(); // 호출 횟수: 2
counter(); // 호출 횟수: 3
return 0;
}
만약 static을 빼고 int n = 0;만 두면 매 호출마다 n이 0으로 다시 초기화되어 출력이 항상 1이 된다. 솔직히 이건 예상 밖이었는데, 제가 학교 첫 학기에 함수 호출 횟수를 누적하는 과제에서 static을 빼먹어 결과가 항상 1만 찍히는 사고를 겪고 나서야 저장 클래스가 단순한 키워드가 아니라 변수의 생존 기간을 결정하는 핵심 속성이라는 점을 손끝으로 받아들였다. 결국 변수는 단순히 값을 담는 그릇이 아니라, 자료형·크기·저장 위치·생존 기간이 결합된 복합적 개념이며, C언어의 모든 기능은 이러한 변수의 정확한 이해 위에서 비로소 자유자재로 활용될 수 있다.
메타 디스크립션: C언어 입문자가 반드시 알아야 할 변수의 개념과 명명 규칙, 기본 데이터 타입(정수형·실수형·문자형)의 크기와 범위, 자동·강제 타입 변환과 4가지 저장 클래스(auto·static·extern·register)를 정보처리기사 실기 빈출 코드 예시와 함께 정리합니다.