Skip to Content
독학사독학사 2단계C프로그래밍06. 기본 자료형과 변수 선언·초기화

이번 문서의 목표: 이 파일을 다 읽으면 C의 정수형·실수형·문자형이 각각 몇 바이트를 차지하고 어떤 값을 표현할 수 있는지 말하고, 형 변환이 일어날 때 값이 왜 그렇게 바뀌는지 계산으로 설명할 수 있다.

왜 자료형의 크기까지 알아야 하는가

3편에서 자료형의 이름과 영문 용어를 훑어봤다면, 이번 편은 “그 자료형이 메모리를 몇 바이트(byte) 차지하고, 그 안에 어떤 범위의 값을 담을 수 있는가”까지 파고든다. C는 자바(Java)와 달리 정수형의 크기가 표준에서 최소 크기만 보장할 뿐 컴파일러·시스템마다 조금씩 다를 수 있고, 서로 다른 자료형끼리 연산하면 값이 예상과 다르게 바뀌는 형 변환(type conversion)이 시험에서 자주 함정으로 등장한다. “정수 두 개를 나눴는데 왜 소수점이 사라지는가”, “문자형 변수에 큰 정수를 넣었더니 왜 이상한 값이 나오는가” 같은 문제가 모두 이번 편의 내용에서 나온다.

쉽게 말하면: 자료형은 변수가 살 집의 평수(크기)와 그 안에 넣을 수 있는 짐(값)의 최대치를 미리 정해 놓은 규격이다. 규격보다 큰 짐을 넣으려 하면 짐이 잘리거나 엉뚱한 모습이 된다.

기본 자료형: 크기와 표현 범위

C의 기본 자료형은 크게 정수형(integer type)과 실수형(floating-point type), 그리고 문자형(character type)으로 나뉜다. 아래 표는 많은 시스템(64비트 환경 기준)에서 일반적으로 쓰이는 크기다. 정확한 크기는 시스템마다 다를 수 있으므로, 시험에서는 sizeof로 직접 확인하는 방법을 함께 알아 두는 것이 중요하다.

자료형영문 이름일반적인 크기대략적인 표현 범위
charcharacter1바이트-128 – 127 (부호 있음 기준)
shortshort int2바이트-32768 – 32767
intinteger4바이트약 -21억 – 21억
longlong int4바이트 또는 8바이트(시스템에 따라 다름)int보다 크거나 같은 범위
floatfloating point4바이트약 소수점 6–7자리 정밀도
doubledouble precision floating point8바이트약 소수점 15–16자리 정밀도

char는 이름은 “문자”지만 실제로는 1바이트 크기의 작은 정수형이다. 'A' 같은 문자를 저장할 때는 내부적으로 그 문자에 대응하는 아스키(ASCII) 코드 값(정수)이 저장된다. 예를 들어 'A'는 65, '0'은 48이라는 정수값으로 저장된다.

#include <stdio.h> int main(void) { char ch = 'A'; int code = ch; /* 문자가 정수로 암시적 변환됨 */ printf("ch=%c, code=%d\n", ch, code); return 0; }
ch=A, code=65

쉽게 말하면: char는 겉보기엔 글자를 담는 그릇이지만, 실제 창고(메모리) 안에는 그 글자에 해당하는 번호표(아스키 코드)만 들어 있다.

sizeof 연산자로 자료형의 실제 크기 확인하기

sizeof는 연산자(operator)이지 함수가 아니지만, 함수처럼 괄호를 붙여 쓰는 경우가 많다. 어떤 자료형이나 변수가 메모리에서 차지하는 바이트 수를 컴파일 시점에 계산해 반환한다.

#include <stdio.h> int main(void) { printf("char: %zu byte\n", sizeof(char)); printf("int: %zu byte\n", sizeof(int)); printf("long: %zu byte\n", sizeof(long)); printf("float: %zu byte\n", sizeof(float)); printf("double: %zu byte\n", sizeof(double)); return 0; }
char: 1 byte int: 4 byte long: 8 byte float: 4 byte double: 8 byte

sizeof의 결과 자료형은 size_t라는 부호 없는 정수형(unsigned integer type)이며, printf로 출력할 때는 %zu 서식 지정자(format specifier)를 쓰는 것이 표준에 맞다. 시험에서는 int가 정확히 4바이트라고 단정하는 보기가 함정으로 나올 수 있으므로, “표준은 최소 크기만 보장하며 실제 크기는 시스템에 따라 다를 수 있다, 확인하려면 sizeof를 쓴다”는 원칙을 기억해야 한다.

변수 선언과 초기화

변수를 만들 때는 선언(declaration)과 초기화(initialization)를 구분해야 한다. 선언은 “이런 이름과 자료형의 변수를 쓰겠다”고 알리는 것이고, 초기화는 그 변수에 처음 값을 넣어 주는 것이다.

int a; /* 선언만 함 — 값은 정해지지 않은 쓰레기 값(garbage value) */ int b = 10; /* 선언과 동시에 초기화 */ int c, d = 5; /* c는 선언만, d는 초기화됨 */

자주 틀리는 점: 지역 변수를 초기화하지 않고 바로 사용하면, 그 변수에는 이전에 그 메모리 자리를 쓰던 다른 데이터의 흔적이 그대로 남아 있을 수 있다. 이를 쓰레기 값(garbage value)이라 부르며, 실행할 때마다 다른 값이 나올 수 있어 예측 불가능한 동작의 원인이 된다. 전역 변수와 정적 변수는 명시적으로 초기화하지 않아도 자동으로 0으로 초기화되지만, 지역 변수는 자동으로 초기화되지 않는다는 차이를 5편의 메모리 모델과 연결해 기억해야 한다.

#include <stdio.h> int global_x; /* 전역 변수 — 자동으로 0 초기화 */ int main(void) { int local_y; /* 지역 변수 — 초기화되지 않으면 쓰레기 값 */ printf("global_x=%d\n", global_x); /* printf("local_y=%d\n", local_y); 를 하면 예측 불가능한 값이 나올 수 있어 시험 답안에서 피해야 할 코드다 */ return 0; }
global_x=0

암시적 형 변환과 명시적 형 변환

서로 다른 자료형끼리 연산하거나 대입할 때, C는 자동으로 한쪽의 자료형을 다른 쪽에 맞춰 바꾸는데 이를 암시적 형 변환(implicit conversion)이라 한다. 프로그래머가 (자료형) 형태로 직접 지시해서 바꾸는 것은 명시적 형 변환(explicit conversion), 흔히 형 변환 연산(형 캐스팅, type casting)이라 부른다.

정수 나눗셈의 함정

#include <stdio.h> int main(void) { int a = 7, b = 2; double result1 = a / b; /* 정수끼리 나눈 뒤 double에 대입 */ double result2 = (double)a / b; /* a를 먼저 double로 변환 후 나눗셈 */ printf("result1=%.1f\n", result1); printf("result2=%.1f\n", result2); return 0; }
result1=3.0 result2=3.5
변수계산 과정결과
result1a / b가 먼저 정수끼리 계산되어 7 / 2 = 3(소수점 버림)이 된 뒤, 이 정수 3double로 변환되어 대입됨3.0
result2(double)aa를 먼저 7.0으로 명시적 변환한 뒤 7.0 / 2를 계산하므로 실수 나눗셈이 적용됨3.5

이 예시가 독학사 C프로그래밍 시험에서 가장 자주 나오는 형 변환 함정이다. 연산은 대입(=)이 일어나기 전에 먼저 끝난다는 순서를 기억해야 한다. result1의 경우 a / b라는 정수 나눗셈이 먼저 완전히 끝나 정수 결과(3)가 만들어진 다음에야, 그 결과가 double로 바뀌어 result1에 저장된다. 이미 소수점 이하가 버려진 뒤이므로 double로 바뀌어도 3.5가 될 수 없다.

쉽게 말하면: 정수 나눗셈은 계산이 끝난 뒤 초대장(형 변환)을 보내는 것과 같다. 계산 자체는 이미 정수 세계에서 끝나 버렸기 때문에, 나중에 실수 세계로 초대해도 이미 버려진 소수점은 되살아나지 않는다.

정수형 사이의 크기 차이로 인한 값 손실

#include <stdio.h> int main(void) { int big = 300; char small = big; /* int(4바이트)를 char(1바이트)에 대입 */ printf("big=%d, small=%d\n", big, small); return 0; }
big=300, small=44

int는 4바이트로 300이라는 값을 온전히 담을 수 있지만, char는 1바이트(부호 있는 경우 -128~127)이기 때문에 300을 그대로 담을 수 없다. 이때는 값이 잘려서(truncation) 저장되는데, 300을 2진수로 표현한 값의 하위 1바이트만 남기 때문에 44라는, 언뜻 보기엔 무관해 보이는 값이 나온다.

300=256+44300 = 256 + 44
  • 300에서 char 1바이트가 표현할 수 있는 범위(256으로 한 바퀴 도는 구조)를 넘어간 부분(256)을 뺀 나머지 44만 하위 바이트에 남는다.

자주 틀리는 점: 큰 자료형에서 작은 자료형으로 대입할 때 “자동으로 반올림되거나 오류가 난다”고 착각하기 쉽다. 실제로는 컴파일 경고만 발생할 뿐 오류 없이 그대로 실행되며, 값은 하위 바이트만 남기고 잘린다. 이 때문에 실행은 되지만 결과가 프로그래머의 의도와 다른, 찾기 어려운 논리 오류(logic error)가 만들어진다.

자료형별 서식 지정자와 흔한 실수

printfscanf에서 자료형에 맞는 서식 지정자(format specifier)를 쓰지 않으면 정의되지 않은 동작(undefined behavior)이 발생할 수 있다.

자료형printf 서식 지정자scanf 서식 지정자
int%d%d
char%c%c
float%f%f
double%f%lf
long%ld%ld

floatprintf에서 %f로 출력하면 되지만, scanffloat 변수에 값을 입력받을 때는 %f, double 변수에 입력받을 때는 반드시 %lf를 써야 한다는 점이 시험에서 자주 나오는 비대칭 포인트다. printf는 인자가 자동으로 double로 승격(promotion)되어 전달되기 때문에 float이든 double이든 %f로 통일해서 출력할 수 있지만, scanf는 실제 메모리 주소에 몇 바이트를 써넣을지 정확히 알아야 하므로 floatdouble의 서식을 반드시 구분해야 한다.

핵심 정리

  • C의 기본 자료형은 정수형(char, short, int, long)과 실수형(float, double)으로 나뉘며, 정확한 크기는 시스템마다 다를 수 있어 sizeof로 확인한다.
  • char는 실제로는 1바이트 정수형이며, 문자는 내부적으로 아스키 코드 값(정수)으로 저장된다.
  • 지역 변수는 초기화하지 않으면 쓰레기 값을 가지지만, 전역·정적 변수는 자동으로 0으로 초기화된다.
  • 정수끼리 나눈 결과는 대입 전에 이미 정수로 확정되므로, 실수 나눗셈을 하려면 연산 이전에 명시적으로 형 변환해야 한다.
  • 큰 자료형의 값을 작은 자료형에 대입하면 오류 없이 하위 바이트만 남고 값이 잘린다.
  • scanf에서 float%f, double%lf를 반드시 구분해서 써야 한다.

마무리 복습

문제 14지선다
다음 중 char 자료형에 대한 설명으로 옳은 것은?
문제 24지선다
다음 코드를 실행했을 때 result의 값은?
int a = 7, b = 2;
double result = a / b;
문제 34지선다
다음 코드를 실행했을 때 발생하는 현상으로 옳은 것은?
int big = 300;
char small = big;
문제 44지선다
지역 변수와 전역 변수의 초기화에 대한 설명으로 옳은 것은?
문제 54지선다
scanf로 double형 변수에 값을 입력받을 때 사용해야 하는 서식 지정자는?
문제 64지선다
sizeof 연산자에 대한 설명으로 옳지 않은 것은?

참고 자료

Last updated on