작은 프로그램 안에 들어 있는 큰 세계
이제 진짜 C 프로그램을 들여다볼 시간입니다. 프로그래밍을 처음 배울 때 가장 많이 만나는 예제는 Hello, World!입니다. 화면에 글자 한 줄을 출력하는 아주 작은 프로그램이지요. 너무 짧아서 별것 아닌 것처럼 보일 수 있습니다.
하지만 C에서는 이 짧은 예제 안에 중요한 구조가 거의 모두 들어 있습니다. 프로그램의 시작점, 외부 기능을 가져오는 방법, 화면 출력, 문장의 끝, 코드 블록, 실행 결과까지 한 번에 만날 수 있습니다.
먼저 아래 코드를 작성해 봅시다.
#include <stdio.h>
int main(void)
{
printf("Hello, World!n");
return 0;
}파일 이름은 예를 들어 hello.c라고 저장합니다. 그런 다음 컴파일하고 실행하면 다음과 같은 결과가 나옵니다.
Hello, World!화면에 글자 한 줄을 찍었을 뿐인데, 컴퓨터 안에서는 꽤 많은 일이 일어났습니다. 컴파일러는 우리가 쓴 C 코드를 읽고, 문법이 맞는지 검사하고, 기계가 실행할 수 있는 형태로 바꿉니다. 그리고 실행 파일이 시작되면 운영체제는 프로그램을 메모리에 올리고, CPU는 약속된 시작점부터 명령을 실행합니다.
그 시작점이 바로 main 함수입니다.

프로그램은 어디서 시작할까?
C 프로그램을 실행하면 컴퓨터가 파일의 첫 줄부터 무조건 실행한다고 생각하기 쉽습니다. 하지만 실제로는 그렇지 않습니다. C 프로그램의 실행은 main 함수에서 시작됩니다.
int main(void)
{
printf("Hello, World!n");
return 0;
}여기서 main은 함수 이름입니다. 함수는 여러 명령을 묶어 이름을 붙인 코드 덩어리라고 생각하면 됩니다. 아직 함수를 자세히 배우지는 않았지만, 지금은 이렇게 이해해도 충분합니다.
main 함수는 C 프로그램의 출발선입니다.
프로그램 실행
↓
운영체제가 실행 파일을 메모리에 올림
↓
main 함수 호출
↓
printf 실행
↓
return 0으로 프로그램 종료조금 더 코드와 연결해 보면 다음과 같습니다.
#include <stdio.h> ← 컴파일 전에 필요한 정보를 가져옴
int main(void) ← 프로그램 실행 시작점
{
printf(...); ← 화면에 글자 출력
return 0; ← 프로그램을 정상 종료
}여기서 중요한 점이 하나 있습니다. #include <stdio.h>는 실행되는 문장이 아닙니다. 프로그램이 실행된 뒤에 CPU가 이 줄을 만나서 처리하는 것이 아닙니다. 이 줄은 컴파일 전에 전처리기라는 도구가 먼저 처리합니다. 전처리기는 컴파일러가 본격적으로 코드를 해석하기 전에 필요한 준비 작업을 해 줍니다.
반면 printf("Hello, World!n");와 return 0;은 main 함수가 실행될 때 차례대로 실행되는 문장입니다.
int main(void)를 천천히 읽어 보기
int main(void)는 처음 보면 암호처럼 보입니다. 하지만 쪼개서 보면 생각보다 단순합니다.
int main(void)main은 함수 이름입니다. C 프로그램은 여기서 시작합니다. void는 이 함수가 외부에서 값을 받지 않는다는 뜻입니다. 지금 프로그램은 실행할 때 추가 정보를 받지 않으므로 void라고 적습니다.
앞의 int는 이 함수가 정수 값을 돌려준다는 뜻입니다. main 함수가 돌려주는 값은 운영체제에게 전달됩니다. 프로그램이 잘 끝났는지, 문제가 있었는지 알려 주는 신호라고 생각하면 됩니다.
return 0;이 문장은 "프로그램이 정상적으로 끝났습니다"라는 의미로 관습적으로 사용됩니다. 보통 0은 성공을 뜻하고, 0이 아닌 값은 오류나 비정상 종료를 나타내는 데 쓰입니다.
그래서 가장 기본적인 C 프로그램의 뼈대는 다음처럼 기억할 수 있습니다.
int main(void)
{
/* 여기부터 실행할 코드를 쓴다. */
return 0;
}지금은 이 구조를 완벽하게 외우려고 하기보다, main 안쪽이 실제 프로그램의 본문이라는 감각을 갖는 것이 중요합니다.
#include <stdio.h>는 왜 필요할까?
이번에는 맨 위의 줄을 보겠습니다.
#include <stdio.h>이 줄은 stdio.h라는 헤더 파일을 포함하라는 뜻입니다. 헤더 파일은 어떤 기능을 사용하기 위해 필요한 선언 정보를 담고 있는 파일입니다.
우리가 사용한 printf는 C 표준 라이브러리에 들어 있는 출력 함수입니다. 표준 라이브러리는 C가 기본으로 제공하는 도구 상자라고 생각하면 됩니다. 그중 stdio.h는 표준 입력과 출력에 관련된 정보를 담고 있습니다. stdio는 "standard input/output"의 줄임말입니다.
즉, 다음 코드는 이렇게 말하는 것과 비슷합니다.
#include <stdio.h>"이 프로그램에서 표준 입출력 기능을 사용할 예정이니, 그 기능들의 사용법을 미리 알려 주세요."
컴파일러는 printf라는 이름을 만났을 때 이 함수가 어떤 형태로 사용되는지 알아야 합니다. printf가 함수인지, 어떤 값을 받는지, 어떤 결과를 돌려주는지에 대한 정보가 필요합니다. 그 정보가 stdio.h에 선언되어 있습니다.
만약 이 줄을 빼고 컴파일하면 환경에 따라 경고나 오류가 나올 수 있습니다.
int main(void)
{
printf("Hello, World!n");
return 0;
}예를 들어 컴파일러는 이런 식으로 말할 수 있습니다.
hello.c:3:5: warning: implicit declaration of function 'printf'뜻을 풀어 보면 이렇습니다.
hello.c 파일의 3번째 줄 5번째 칸 근처에서 문제가 있습니다.
printf라는 함수를 선언도 없이 사용했습니다.처음에는 에러 메시지가 무섭게 보입니다. 하지만 대부분의 컴파일 에러는 몇 가지 단서를 줍니다. 파일 이름, 줄 번호, 그리고 무엇이 이상한지에 대한 설명입니다. 이 단서들을 차례로 읽으면 문제를 훨씬 쉽게 찾을 수 있습니다.
printf로 화면에 글자 출력하기
이제 실제로 화면에 글자를 출력하는 줄을 보겠습니다.
printf("Hello, World!n");printf는 화면에 값을 출력하는 함수입니다. 괄호 안에는 출력할 내용을 적습니다. 지금은 큰따옴표로 감싼 문자열을 전달했습니다.
"Hello, World!n"큰따옴표 안에 들어 있는 글자들은 문자열입니다. 문자열은 여러 문자가 이어진 데이터입니다. Hello, World!도 문자열이고, C language도 문자열입니다.
그런데 맨 뒤에 조금 이상한 기호가 있습니다.
n이것은 줄바꿈 문자입니다. 화면에 ``와 n을 그대로 출력하라는 뜻이 아니라, 커서를 다음 줄로 내려가게 하라는 특별한 표시입니다.
다음 두 코드를 비교해 봅시다.
#include <stdio.h>
int main(void)
{
printf("Hello, ");
printf("World!");
return 0;
}실행 결과는 다음과 같습니다.
Hello, World!두 번 출력했지만 줄바꿈이 없으므로 한 줄에 이어서 출력됩니다.
이번에는 n을 넣어 보겠습니다.
#include <stdio.h>
int main(void)
{
printf("Hello,n");
printf("World!n");
return 0;
}실행 결과는 다음과 같습니다.
Hello,
World!n 하나가 출력의 모양을 바꾸었습니다. 작은 기호 하나지만, 프로그램의 결과를 사람이 읽기 좋게 만드는 데 아주 자주 쓰입니다.
세미콜론은 문장의 마침표다
C에서는 대부분의 실행 문장 끝에 세미콜론 ;을 붙입니다.
printf("Hello, World!n");
return 0;한국어 문장이 마침표로 끝나듯, C의 문장은 세미콜론으로 끝난다고 생각하면 됩니다. 물론 모든 곳에 세미콜론이 붙는 것은 아닙니다. 예를 들어 #include 줄이나 함수의 중괄호 뒤에는 세미콜론을 붙이지 않습니다. 하지만 지금 단계에서는 "실행되는 한 문장 끝에는 세미콜론을 붙인다"라고 기억하면 좋습니다.
세미콜론을 빼면 어떤 일이 생길까요?
#include <stdio.h>
int main(void)
{
printf("Hello, World!n")
return 0;
}컴파일하면 다음과 비슷한 오류를 만날 수 있습니다.
hello.c:5:5: error: expected ';' before 'return'이 메시지는 return 앞에서 세미콜론이 필요하다고 말합니다. 여기서 재미있는 점은 실제 실수는 4번째 줄에 있는데, 오류 메시지는 5번째 줄을 가리킬 수 있다는 것입니다. 컴파일러는 4번째 줄에서 문장이 끝났다고 판단하지 못한 채 다음 줄까지 읽다가, return을 보고 "어? 여기 오기 전에 문장이 끝났어야 하는데?"라고 말하는 것입니다.
그래서 컴파일 에러를 볼 때는 오류가 난 줄만 보지 말고, 바로 위 줄도 함께 확인하는 습관이 필요합니다.
중괄호는 코드 블록을 만든다
C 코드에서 중괄호 { }는 코드 블록을 만듭니다. 코드 블록은 여러 문장을 하나의 덩어리로 묶는 경계입니다.
int main(void)
{
printf("Hello, World!n");
return 0;
}여기서 {부터 }까지가 main 함수의 몸체입니다. 프로그램이 main 함수에 들어오면 이 중괄호 안의 문장들이 위에서 아래로 실행됩니다.
중괄호는 단순히 보기 좋게 묶는 표시가 아닙니다. 앞으로 배울 조건문, 반복문, 함수, 구조체에서 계속 등장합니다. C에서 중괄호는 "여기부터 여기까지가 한 묶음입니다"라고 알려 주는 아주 중요한 기호입니다.
간단한 예를 보겠습니다.
#include <stdio.h>
int main(void)
{
printf("An");
{
printf("Bn");
printf("Cn");
}
printf("Dn");
return 0;
}실행 결과는 다음과 같습니다.
A
B
C
D가운데에 있는 중괄호는 B와 C를 하나의 블록으로 묶었습니다. 아직은 별 차이가 없어 보일 수 있습니다. 하지만 나중에 변수를 배우면 이 블록이 변수의 범위, 즉 스코프와 관련된다는 사실을 알게 됩니다. 스코프는 이름이 살아 있는 영역입니다. 어떤 변수를 어디에서 사용할 수 있는지를 결정하는 경계라고 생각하면 됩니다.
예를 들어 아래 코드는 나중에 배울 변수의 관점에서 중요한 의미를 갖습니다.
#include <stdio.h>
int main(void)
{
{
int number = 10;
printf("%dn", number);
}
return 0;
}number라는 변수는 안쪽 중괄호 블록에서 만들어졌습니다. 이 변수는 그 블록 안에서만 사용할 수 있습니다. 지금은 "중괄호는 코드의 경계를 만들고, 나중에는 변수의 사용 범위에도 영향을 준다" 정도만 기억해 두면 됩니다.
주석은 컴퓨터가 읽지 않는 메모다
코드를 쓰다 보면 사람을 위한 설명을 남기고 싶을 때가 있습니다. 이때 주석을 사용합니다. 주석은 컴파일러가 실행 코드로 보지 않는 메모입니다.
C에는 대표적으로 두 가지 주석 방식이 있습니다.
// 한 줄 주석입니다.
/*
여러 줄 주석입니다.
여러 줄에 걸쳐 설명을 쓸 수 있습니다.
*/예제에 주석을 넣어 보면 다음과 같습니다.
#include <stdio.h>
int main(void)
{
// 화면에 인사말을 출력한다.
printf("Hello, World!n");
return 0; // 프로그램을 정상 종료한다.
}주석은 초보자에게 좋은 친구입니다. 하지만 모든 줄에 너무 많은 주석을 달 필요는 없습니다. 좋은 주석은 코드가 "무엇을 하는지"를 그대로 반복하기보다, "왜 이렇게 했는지"를 설명할 때 빛납니다.
예를 들어 다음 주석은 별 도움이 되지 않습니다.
printf("Hello, World!n"); // Hello, World를 출력한다.코드만 봐도 알 수 있는 내용을 그대로 반복하기 때문입니다. 반면 다음과 같은 주석은 상황을 이해하는 데 도움이 됩니다.
// 첫 실행 테스트용 출력. 개발 환경이 제대로 연결되었는지 확인한다.
printf("Hello, World!n");지금 단계에서는 자신이 헷갈리는 부분에 짧게 메모를 남기는 용도로 주석을 활용하면 충분합니다.
컴파일 에러 메시지 읽는 법
C를 배우다 보면 에러 메시지를 자주 만나게 됩니다. 이것은 실패가 아닙니다. 오히려 프로그래밍을 배우는 과정에서 가장 자연스러운 일입니다. 중요한 것은 에러 메시지를 무시하지 않고 읽는 습관입니다.
컴파일 에러는 보통 다음 정보를 담고 있습니다.
어떤 파일에서 문제가 생겼는지
몇 번째 줄, 몇 번째 칸 근처에서 문제가 발견되었는지
컴파일러가 무엇을 이상하다고 판단했는지
예를 들어 다음 코드는 큰따옴표를 닫지 않았습니다.
#include <stdio.h>
int main(void)
{
printf("Hello, World!n);
return 0;
}컴파일러는 다음과 비슷하게 말할 수 있습니다.
hello.c:5:12: error: missing terminating " character차근차근 읽어 봅시다.
hello.c → 문제가 발견된 파일 이름
5:12 → 5번째 줄 12번째 칸 근처
error → 컴파일을 계속할 수 없는 오류
missing terminating " character
→ 문자열을 끝내는 큰따옴표가 없다이렇게 읽으면 오류 메시지가 조금 덜 무섭습니다. 컴파일러는 화를 내는 것이 아니라, 자신이 이해하지 못한 지점을 알려 주고 있는 것입니다.
이번에는 괄호를 빼 보겠습니다.
#include <stdio.h>
int main(void)
{
printf("Hello, World!n";
return 0;
}오류 메시지는 이런 식일 수 있습니다.
hello.c:5:31: error: expected ')' before ';' token뜻은 "세미콜론이 나오기 전에 닫는 괄호 )가 있어야 한다고 예상했다"입니다. 이 경우에는 printf의 괄호가 제대로 닫혔는지 확인하면 됩니다.
에러를 만났을 때는 다음 순서로 확인해 보세요.
메시지에서 파일 이름과 줄 번호를 먼저 찾습니다.
해당 줄과 바로 위 줄을 함께 봅니다.
세미콜론, 큰따옴표, 괄호, 중괄호가 짝을 이루는지 확인합니다.
첫 번째 에러부터 고칩니다. 뒤의 에러는 첫 번째 실수 때문에 함께 생긴 가짜 에러일 수 있습니다.
처음에는 한 글자 때문에 10분을 헤맬 수도 있습니다. 하지만 그 과정에서 C 문법을 눈으로 익히게 됩니다. 컴파일 에러는 초보자를 괴롭히는 벌칙이 아니라, 코드와 더 가까워지는 훈련 도구입니다.
Hello, World!를 제대로 이해하기
처음의 코드를 다시 봅시다.
#include <stdio.h>
int main(void)
{
printf("Hello, World!n");
return 0;
}이제 각 줄의 의미가 조금 다르게 보일 것입니다.
#include <stdio.h>는 printf를 사용하기 위해 표준 입출력 관련 선언을 가져옵니다. 이 줄은 실행 중에 처리되는 명령이 아니라, 컴파일 전에 준비되는 지시문입니다.
int main(void)는 프로그램의 시작점입니다. 실행 파일이 실행되면 결국 이 함수 안의 코드가 실행됩니다.
{와 }는 main 함수의 몸체를 만듭니다. 이 안에 있는 문장들이 프로그램의 실제 실행 내용입니다.
printf("Hello, World!n");는 화면에 문자열을 출력합니다. n은 줄바꿈을 의미하고, 세미콜론은 이 문장이 끝났음을 나타냅니다.
return 0;은 프로그램이 정상적으로 끝났다는 값을 운영체제에 돌려줍니다.
짧은 프로그램이지만 그 안에는 C의 핵심이 압축되어 있습니다. C는 대충 넘어가는 것을 잘 허락하지 않는 언어입니다. 함수의 시작과 끝, 문장의 끝, 포함해야 할 헤더, 괄호와 따옴표까지 정확히 맞아야 합니다. 처음에는 까다롭게 느껴질 수 있지만, 바로 그 정확함 덕분에 우리는 컴퓨터가 프로그램을 어떤 순서로 읽고 실행하는지 더 선명하게 배울 수 있습니다.
직접 바꿔 보며 감각 만들기
마지막으로 코드를 조금씩 바꿔 보겠습니다. C를 배울 때 가장 좋은 방법은 짧은 코드를 직접 수정하고, 컴파일하고, 결과를 확인하는 것입니다.
먼저 출력할 문장을 바꿔 보세요.
#include <stdio.h>
int main(void)
{
printf("I am learning C!n");
return 0;
}이번에는 여러 줄을 출력해 봅시다.
#include <stdio.h>
int main(void)
{
printf("C is close to the computer.n");
printf("Memory, CPU, and code meet here.n");
printf("Let's begin!n");
return 0;
}실행 결과는 다음과 같습니다.
C is close to the computer.
Memory, CPU, and code meet here.
Let's begin!이번 장에서 꼭 가져가야 할 감각은 단순합니다. C 프로그램은 main에서 시작하고, 중괄호 안의 문장을 위에서 아래로 실행합니다. 화면 출력에는 printf를 사용하고, 이를 위해 stdio.h가 필요합니다. 문장의 끝에는 세미콜론을 붙이고, 에러가 나면 메시지에서 파일 이름과 줄 번호부터 찾습니다.
이제 우리는 C 프로그램의 가장 작은 집을 지었습니다. 다음 장부터는 이 집 안에 값을 저장하는 방을 만들 것입니다. 그 방의 이름이 바로 변수입니다.
이 노트는 보도·비평·교육·연구 목적으로 작성되었습니다. 저작권 문의가 있으시면 에서 알려주세요.
