C언어 제어문 (if, for, while)
프로그램은 본질적으로 위에서 아래로 순차 실행되지만, 그것만으로는 의미 있는 일을 거의 할 수 없다. 어떤 조건에서는 다른 길로 갈라지고, 어떤 조건에서는 같은 작업을 여러 번 반복해야 비로소 알고리즘이 완성된다. 이러한 흐름을 제어하기 위해 C언어가 제공하는 두 가지 도구가 바로 제어문(Control Statement)과 반복문(Loop)이다(출처: cppreference — Statements). 입문자가 가장 먼저 익혀야 할 핵심 문법이며, 이 두 도구를 자유자재로 사용할 수 있어야 변수와 데이터 타입을 다루는 능력이 비로소 살아 움직이는 프로그램으로 변환된다. 본 글은 조건문, 반복문, 그리고 분기를 제어하는 키워드까지 한 번에 정리한다. 제가 학교 C언어 과제에서 가장 자주 만난 사고가 switch 문에서 break를 빠뜨려 다음 case까지 함께 실행되는 일이었고, 그 한 번의 실수가 fall-through라는 용어를 손끝으로 외우게 만들었다.

조건문, if와 switch의 활용
조건문은 특정 조건의 참·거짓에 따라 코드의 실행 경로를 분기시키는 문법이다. C언어에서 사용되는 조건문은 크게 if 계열과 switch 계열로 나뉘며, 각각이 적합한 상황이 분명히 구분된다. 조건이 단순한 참·거짓 분기이거나 비교 연산이 필요한 경우에는 if 문이 적합하고, 한 변수의 여러 가지 값에 따라 분기해야 하는 경우에는 switch 문이 더 효율적이다.
if 문은 가장 기본적인 조건문으로 if (조건) { 실행할 코드 } 형식으로 작성한다. 조건이 참이면 중괄호 안의 코드가 실행되고, 거짓이면 건너뛴다. 양자택일이 필요하면 else 절을 추가해 if (조건) { ... } else { ... } 형식으로 작성한다. 셋 이상의 분기가 필요할 때는 else if를 활용해 다중 조건을 만든다.
#include <stdio.h>
int main(void) {
int score = 85;
if (score >= 90) printf("A\n");
else if (score >= 80) printf("B\n");
else if (score >= 70) printf("C\n");
else printf("F\n");
// 삼항 연산자 — 식 한 줄로 분기
int abs = (score >= 0) ? score : -score;
printf("abs = %d\n", abs);
return 0;
}
여기서 삼항 연산자란 조건 ? 참값 : 거짓값 형식으로 한 줄짜리 분기를 표현하는 식 수준의 조건 연산자를 가리킨다. 변수 할당이나 함수 인자처럼 식 안에서 분기가 필요할 때 매우 유용하다.
switch 문은 한 변수가 여러 개의 특정 값 중 어떤 것과 같은지를 검사할 때 사용한다. switch (변수) { case 값: 코드; break; ... default: 기본 코드; } 형식으로 작성하며, 각 case 끝에 반드시 break를 명시해야 한다. break를 빠뜨리면 해당 case 이후의 모든 case가 연쇄적으로 실행되는 fall-through가 발생한다.
#include <stdio.h>
int main(void) {
char grade = 'B';
switch (grade) {
case 'A': printf("90점 이상\n"); break;
case 'B': printf("80~89점\n"); break;
case 'C': printf("70~79점\n"); break;
default: printf("70점 미만\n");
}
return 0;
}
여기서 fall-through란 한 case의 코드를 실행한 뒤 break를 만나지 못해 다음 case의 코드까지 그대로 흘러 들어가는 동작 방식을 의미한다. 의도적으로 활용할 수도 있지만 대부분의 경우 버그의 원인이 되므로 주의가 필요하다. switch 문은 정수형이나 문자형 같은 이산적인 값에만 사용할 수 있으며, 실수형이나 문자열 비교에는 사용할 수 없다는 제약이 있다.
반복문, for와 while의 차이
반복문은 같은 코드를 여러 번 실행하기 위한 문법이며, C언어는 세 가지 형태의 반복문을 제공한다. for 문, while 문, do-while 문이 그것이며, 세 가지 모두 본질적으로는 같은 일을 하지만 어떤 상황에 어떤 반복문을 쓰느냐가 코드의 가독성과 유지보수성에 큰 영향을 미친다. 사용 시점을 구분하는 기준은 반복 횟수가 사전에 정해져 있는지, 그리고 조건 검사가 실행 전에 이루어지는지 후에 이루어지는지이다.
| 반복문 | 조건 검사 | 최소 실행 | 적합한 상황 |
|---|---|---|---|
for |
시작 전 | 0회 가능 | 반복 횟수가 정해진 경우 |
while |
시작 전 | 0회 가능 | 조건에 따라 반복 |
do-while |
끝난 후 | 최소 1회 보장 | 무조건 한 번은 실행해야 할 때 |
for 문은 반복 횟수가 사전에 정해진 경우에 가장 자주 사용된다. for (초기식; 조건식; 증감식) { ... } 형식으로 작성하며, 초기식은 반복 시작 전에 한 번만 실행되고, 조건식은 매 반복 시작 시에 검사되어 참이면 반복을 계속하고 거짓이면 종료한다. 증감식은 매 반복 끝에 실행된다. 가장 흔한 형태가 for (int i = 0; i < n; i++)로, 0부터 n-1까지 n번 반복하는 패턴이다.
#include <stdio.h>
int main(void) {
// 실기 빈출 — 구구단 한 줄
for (int i = 2; i <= 9; i++) {
for (int j = 1; j <= 9; j++) {
printf("%d x %d = %d\t", i, j, i * j);
}
printf("\n");
}
return 0;
}
while 문은 반복 횟수가 미리 정해지지 않고 조건에 따라 결정되는 경우에 사용한다. while (조건식) { ... } 형식이며, 조건식이 참인 동안에만 반복을 수행한다. 조건이 처음부터 거짓이면 단 한 번도 실행되지 않을 수 있다는 점이 특징이다.
do-while 문은 while 문과 거의 동일하지만 결정적인 차이가 있다. do { ... } while (조건식); 형식으로 작성하며, 조건 검사가 코드 블록 실행 후에 이루어진다는 점이다. 따라서 do-while 문은 조건과 무관하게 최소 한 번은 반드시 실행된다는 강력한 보장을 제공한다. 메뉴 표시처럼 적어도 한 번은 무조건 보여줘야 하는 작업이나, 사용자 입력을 받은 뒤 유효성을 검증해 잘못되면 다시 받는 패턴에 적합하다. 마지막에 세미콜론을 빠뜨리지 않아야 한다는 점이 자주 실수하는 부분이다. 솔직히 제 경험상 학교 시험에서 do-while 문제를 가장 자주 틀렸는데, "조건이 거짓이어도 한 번은 실행된다"는 한 줄을 외운 후로는 출력 결과 추적이 안정되었다.
실기 빈출 예제 — 분기 제어 (break·continue·goto)
반복문 내부에서 흐름을 세밀하게 조절하기 위해 사용하는 키워드가 분기 제어문이다. C언어에서 자주 사용되는 분기 제어 키워드는 break, continue, return, 그리고 goto 네 가지이며, 정보처리기사 실기에서 출력 결과 추적 문제의 단골 소재이다.
| 키워드 | 동작 | 영향 범위 |
|---|---|---|
break |
즉시 종료 | 가장 가까운 반복문 또는 switch 하나 |
continue |
현재 회차만 건너뜀 | 반복은 계속 |
return |
함수 종료 | 함수 전체 |
goto |
라벨로 점프 | 같은 함수 안 어디든 |
#include <stdio.h>
int main(void) {
// 1부터 10까지 중 홀수만 출력하다가 7을 만나면 종료
for (int i = 1; i <= 10; i++) {
if (i % 2 == 0) continue; // 짝수는 건너뜀
if (i == 7) break; // 7을 만나면 반복 종료
printf("%d ", i);
}
// 출력: 1 3 5
printf("\n");
return 0;
}
위 코드의 출력은 1 3 5이다. continue가 짝수를 모두 걸러내고, 7에서 break를 만나기 때문에 7과 9는 출력되지 않는다. 솔직히 이건 예상 밖이었는데, 학교 동기 중 절반이 같은 문제에서 "1 3 5 7" 또는 "1 3 5 7 9"라고 답해 틀린 적이 있고, break는 반복을 끝내고 continue는 그 회차만 건너뛴다는 한 줄을 외운 사람만 정답을 맞췄다는 점이 가장 인상적이었다.
return은 반복문이나 함수 본체 어디에서든 함수 자체를 즉시 종료하고 호출자에게 값을 반환한다. 함수 안에 있는 반복문에서 return을 만나면 break처럼 반복을 빠져나가는 것이 아니라 함수 전체가 종료된다는 점이 결정적인 차이이다. goto는 라벨이 붙은 위치로 무조건 점프하는 키워드로, goto 라벨; 형식으로 사용하며 점프 대상에는 라벨:을 붙여 표시한다. goto는 코드의 흐름을 예측하기 어렵게 만들어 가독성과 유지보수성을 크게 떨어뜨리기 때문에 일반적으로 사용을 자제하는 것이 권장된다(출처: Dijkstra — Go To Statement Considered Harmful). 다만 깊게 중첩된 반복문에서 한 번에 모든 반복을 빠져나갈 때나, 에러 처리 후 자원 해제로 점프해야 할 때 같은 매우 제한적인 상황에서만 신중하게 사용하는 것이 표준이다. 이 네 가지 분기 제어 키워드를 적절히 조합하면 어떤 복잡한 흐름도 명확하게 표현할 수 있으며, 좋은 C언어 프로그래머는 키워드 선택만으로도 코드의 의도를 명확히 드러낼 줄 아는 사람이라 할 수 있다.
메타 디스크립션: C언어의 핵심 흐름 제어 도구인 조건문(if·switch), 반복문(for·while·do-while), 그리고 분기 제어 키워드(break·continue·return·goto)의 사용법과 차이를 정보처리기사 실기 빈출 코드 예시와 함께 정리합니다.