C언어 첫걸음
목차 23
C언어 첫걸음은 4과목 코드 추적의 출발점이다. 변수·자료형·입출력·연산자·조건문·반복문·변수 범위·배열을 코드로 직접 따라가며 출력값을 도출한다. 매 회차 1문항 이상 꾸준히 나오는 빈출 영역으로, 정수 나눗셈 버림 · scanf
&누락 · switch Fall-through · 연산자 우선순위 · static 초기화 · 배열 인덱스 여섯 함정이 단골이다. 38강에서 잡은 ★순반선★(순차·반복·선택)이 여기서if·switch·for·while로 실제 코드가 된다.핵심 암기: 자료형 4종 ★자정실문★(정수·실수·문자·문자열 — 크기 1·2·4·8) · 연산자 7대 ★전증감산논비대★(전위·증가·감소·산술·논리·비교·대입) + 우선순위 5단계(곱셈 > 덧셈 > 비교 > 논리 > 대입) · C = 1972 데니스 리치 · UNIX · 컴파일러 · 3세대 고급 · 절차적 · 함정 6쌍(
5/2=2· scanf&· Fall-through ·2+3*4=14· static 첫 호출만 · 인덱스 0~크기-1)
PART A — C의 정체성
C언어 정체성과 Hello World ·언어 정의·
[정의] C언어 = 1972년 데니스 리치(Dennis Ritchie)가 UNIX 운영체제를 만들기 위해 개발한 절차적·구조적 고급 언어. 한 줄 분류로 줄이면 컴파일러로 번역되는 3세대 고급 절차적 언어다.
[표] C 분류 3축
| 분류 축 | C의 위치 | 의미 |
|---|---|---|
| 번역 방식 | 컴파일러 계열 | gcc hello.c -o hello 한 줄로 전체를 번역 |
| 언어 세대 | 3세대 고급 언어 | int a = 5; 사람이 읽는 코드 |
| 패러다임 | 절차적 언어 | 위에서 아래로 순서대로 실행 |
[코드] 세상에서 가장 유명한 첫 C 프로그램
#include <stdio.h> /* ① 헤더 — printf 사용 준비 */
int main() /* ② 시작점 — 모든 C는 main부터 */
{
printf("Hello, World!\n"); /* ③ 출력 — \n은 줄바꿈 */
return 0; /* ④ 정상 종료 신호 */
}
💡 #include=레시피 가져오기 · main()=시작 버튼 · printf()=완성된 요리 내놓기 · return 0="잘 끝났어요" 인사.
🔑 암기 "C = 1972 데니스 리치 UNIX용 — 컴파일러 · 고급 · 절차적 세 묶음"
⚠️ 함정 "C는 객체지향 언어" ❌(→ 절차적·C++/C#이 객체지향) / "C는 인터프리터 언어" ❌(→ 컴파일러). C 프로그램의 시작점은 main().
🎯 빈출 C 정체성·시작점 매칭. 38강 ★순반선★(순차·반복·선택)이 여기서 실제 코드로 회수된다.
PART B — 변수와 자료형
변수와 명명 규칙 ·자료형·
[정의] 변수(Variable) = 데이터를 저장하는 메모리의 한 칸에 이름표를 붙인 것. 선언만 하고 초기화하지 않은 변수의 값은 쓰레기 값(Garbage Value) — 0이 아니다.
[코드]
int age; /* 선언 — 서랍 만들기 (값은 쓰레기) */
age = 30; /* 대입 — 서랍에 30 넣기 */
int height = 175; /* 선언 + 초기화 — 동시에 175 넣기 (권장) */
[표] 변수 이름 규칙 4조건
| 규칙 | OK | NO |
|---|---|---|
영문자·숫자·_만 |
user_name |
user-name |
| 숫자로 시작 안 됨 | var1 |
2nd_var |
| 예약어 안 됨 | myInt |
int, for |
| 대소문자 구분 | Age ≠ age |
— |
💡 서랍에 이름표 '연필'을 붙이고 안에 5자루를 넣으면 코드로는 pencils = 5;.
🔑 암기 "변수 = 서랍 + 이름표 + 값. 명명 4조건 = 영문자·숫자·_만 / 숫자 시작 X / 예약어 X / 대소문자 구분"
⚠️ 함정 "초기화 안 한 변수는 0" ❌(→ 쓰레기 값).
🎯 빈출 명명 규칙 4조건·쓰레기 값.
★자정실문★ — 자료형 4종 ·자료형·시험 1순위·
[정의] C 자료형은 4종 = 정수 · 실수 · 문자 · 문자열. 두음 ★자정실문★.
[표] 자료형 4종 + 크기
| 분류 | 자료형 | 크기 | 비고 |
|---|---|---|---|
| 정수 | char |
1바이트 | 정수형이지만 문자 저장용으로 주로 씀 |
short |
2바이트 | 작은 정수 | |
int |
4바이트 | 기본 정수형 | |
long long |
8바이트 | 매우 큰 정수 | |
| 실수 | float |
4바이트 | 약 6~7자리 |
double |
8바이트 | 약 15~16자리 | |
| 문자 | char |
1바이트 | 한 글자·작은따옴표·ASCII 정수로 저장 |
| 문자열 | char 배열 |
— | 큰따옴표·끝에 \0(널 문자) |
[코드] 문자와 ASCII
char letter = 65; /* 65 = 문자 'A' (ASCII) */
printf("%c\n", letter); /* 출력: A */
printf("%d\n", letter); /* 출력: 65 */
char name[10] = "Hong"; /* 메모리: ['H']['o']['n']['g']['\0']... */
💡 ASCII 핵심 3종 — 'A'=65 · 'a'=97 · '0'=48 (대문자 + 32 = 소문자). 작은따옴표 'A'는 도장 한 개(char 1B), 큰따옴표 "A"는 도장을 이어 붙인 배열(['A']['\0'] 2바이트).
🔑 암기 "★자정실문★ — 정수 1·2·4·8 / 실수 float 4 · double 8 / 문자 char 1B 작은따옴표 / 문자열 char 배열 큰따옴표 끝에 \0"
⚠️ 함정 "int = 8바이트" ❌(→ 4) / "double = 4바이트" ❌(→ 8) / "C에 문자열 타입이 있다" ❌(→ char 배열로 표현, 별도 타입 없음).
🎯 빈출 자료형 크기 짝짓기가 거의 매회. float(4) ↔ double(8) 바꿔치기가 단골.
정수 나눗셈과 형 변환 ·자료형·시험 1순위·
[정의] 정수 ÷ 정수 = 정수(소수점 이하 버림). 형 변환(Type Casting)으로 정수를 실수로 바꿀 때도, 실수를 정수로 바꿀 때는 버림(반올림 아님).
[코드]
printf("%d\n", 5 / 2); /* 출력: 2 — 소수점 이하 버림 */
printf("%f\n", 5.0 / 2.0); /* 출력: 2.500000 */
int a = 5, b = 2;
double c = a / b; /* c = 2.0 — 정수 나눗셈 후 대입 (함정!) */
double d = (double)a / b; /* d = 2.5 — 캐스팅 먼저 */
int e = (int)3.7; /* e = 3 — 반올림 아니라 버림! */
⚠️ 함정 double c = 5 / 2;로 써도 c에는 2.0이 들어간다 — 이미 정수가 된 뒤에 대입되기 때문. 한쪽이라도 실수(5.0 / 2 또는 (double)a / b)여야 2.5가 나온다. (int)3.7은 3(버림). 매 회차 한 문제는 여기서 나온다.
🔑 암기 "정수 나눗셈은 무조건 버림 5/2=2 · 캐스팅도 버림 (int)3.7=3 · 한쪽이라도 실수여야 실수 나눗셈"
🎯 빈출 double c = a / b 형태의 결과 예측이 매 회차 단골.
PART C — 입출력
printf — 포맷과 옵션 ·입출력·
[정의] printf(print formatted) = 화면에 값을 출력하는 형식 지정 함수. 빈 칸(%d 등)에 변수 값을 끼워 넣는다.
[표] 포맷 지정자 7종
| 지정자 | 의미 | 예시 → 출력 |
|---|---|---|
%d |
정수 | printf("%d", 100) → 100 |
%f |
실수 | printf("%f", 3.14) → 3.140000 |
%lf |
실수(double) | printf에서는 %f도 OK |
%c |
문자 | printf("%c", 'A') → A |
%s |
문자열 | printf("%s", "Hong") → Hong |
%o |
8진수 | printf("%o", 8) → 10 |
%x |
16진수 | printf("%x", 15) → f |
[표] 옵션 4종
| 옵션 | 의미 | 예시 → 출력 |
|---|---|---|
%5d |
폭 5칸 오른쪽 정렬 | printf("%5d", 42) → 42 |
%-5d |
폭 5칸 왼쪽 정렬 | printf("%-5d", 42) → 42 |
%05d |
폭 5칸 0 채우기 | printf("%05d", 42) → 00042 |
%.2f |
소수점 2자리 | printf("%.2f", 3.14159) → 3.14 |
💡 명함의 빈 칸에 도장 찍기 — printf("나이: %d살", age)는 '나이: __살' 명함의 %d 자리에 30을 찍는 것. %.2f는 셋째 자리에서 반올림해 3.14.
🔑 암기 "%d %f %c %s 4종이 1순위 + 옵션 = 폭 · 왼쪽(-) · 0채움(0) · 소수점(.)"
🎯 빈출 %o(8진)·%x(16진) 변환, 옵션 출력 폭.
scanf — 변수 앞에 & 필수 ·입출력·
[정의] scanf(scan formatted) = 키보드 입력을 받아 변수에 저장하는 함수. 값을 받을 변수의 주소가 필요해 변수 앞에 &를 붙인다.
[표] scanf 함정 4종
| 함정 | 잘못된 코드 | 정답 |
|---|---|---|
& 누락 |
scanf("%d", age); |
scanf("%d", &age); |
double에 %f |
scanf("%f", &pi); |
scanf("%lf", &pi); |
| 자료형 불일치 | int a; scanf("%f", &a); |
int a; scanf("%d", &a); |
문자열에 & |
scanf("%s", &name); |
scanf("%s", name); — 배열은 & 없이 |
[표] printf vs scanf
| 항목 | printf |
scanf |
|---|---|---|
| 방향 | 변수 → 화면 | 키보드 → 변수 |
| 변수 표기 | 그냥 변수 이름 | &변수 (주소) |
| double | %f도 OK |
%lf 필수 |
💡 scanf는 택배 기사 — 입력값을 보내려면 변수의 주소(&age)를 알려줘야 한다. 변수 이름만 쓰면 '주소 모름'이라 못 보낸다. 단, 배열(문자열)은 이름 자체가 주소라 & 없이.
🔑 암기 "scanf는 & 필수 + double은 %lf + 배열은 & 없이"
⚠️ 함정 scanf 변수에 & 빠뜨리기 / 문자열(배열)에 & 붙이기.
🎯 빈출 & 누락·%lf가 매 회차 단골.
PART D — 연산자
★전증감산논비대★ — 연산자 7대와 우선순위 ·연산자·시험 1순위·
[정의] C 연산자는 7대 분류 = 전위 · 증가 · 감소 · 산술 · 논리 · 비교 · 대입. 두음 ★전증감산논비대★.
[표] 연산자 7대 — ★전증감산논비대★ 순서
| 글자 | 분류 | 연산자 | 핵심 |
|---|---|---|---|
| 전 | 전위 | ++a --a |
먼저 증가/감소 후 사용 |
| 증 | 증가 | a++ ++a |
1씩 증가 |
| 감 | 감소 | a-- --a |
1씩 감소 |
| 산 | 산술 | + - * / % |
%는 나머지 (정수에만) |
| 논 | 논리 | && || ! |
AND · OR · NOT (단락 평가) |
| 비 | 비교 | == != < > <= >= |
결과는 참=1 · 거짓=0 (int) |
| 대 | 대입 | = += -= *= /= |
=(대입) ≠ ==(비교) |
삼항 연산자 조건 ? A : B는 7대 분류에 들지 않는 별도 연산자로, if-else를 한 줄로 압축한다(조건문 카드 참고).
[흐름] 우선순위 5단계 사다리
높음 ① 단항 (++ -- !)
② 곱셈류 (* / %)
③ 덧셈류 (+ -)
④ 비교 (< > <= >= == !=)
⑤ 논리 (&& 먼저, || 나중)
낮음 ⑥ 대입 (= += ...)
[코드]
int a = 5;
printf("%d\n", ++a); /* 6 — 먼저 증가 후 사용 */
printf("%d\n", a++); /* 6 — 사용 후 증가 → 다음 줄에서 a=7 */
printf("%d\n", 2 + 3 * 4); /* 14 — 곱셈 먼저 */
💡 우선순위는 수학 시간 그대로 — 곱셈 먼저, 덧셈 나중, 그다음 비교·논리·대입. 2 + 3 * 4 = 14(곱셈 먼저), a && b || c는 (a && b) || c(AND가 OR보다 우선).
🔑 암기 "★전증감산논비대★ + 우선순위 곱셈 > 덧셈 > 비교 > 논리 > 대입. && 먼저 || 나중"
⚠️ 함정 =(대입)와 ==(비교) 혼동 — if (a = 3)은 a에 3을 넣고 항상 참 / 2 + 3 * 4 = 20 ❌(→ 14) / 전위는 먼저 증가, 후위는 사용 후 증가.
🎯 빈출 연산자 우선순위·증감 시점이 매 회차. %는 정수에만.
PART E — 조건문
if · else if ·제어·
[정의] if · else if = 위에서부터 차례로 조건을 확인하고 처음 만나는 참에서 멈춘다. C의 참/거짓 = 0이 거짓, 0이 아닌 모든 값이 참(별도 bool 타입 없음).
[코드]
int score = 75;
if (score >= 90) printf("A\n");
else if (score >= 80) printf("B\n");
else if (score >= 70) printf("C\n"); /* 75는 여기서 멈춤 → 출력: C */
else printf("F\n");
💡 백화점 안내 직원 — '90점 이상? 아뇨. 80점? 아뇨. 70점? 네!' → C층. 위에서부터 확인하고 처음 맞는 답에서 멈춘다.
🔑 암기 "위에서부터 처음 만나는 참에서 멈춤 · 0=거짓 / 나머지 전부 참"
⚠️ 함정 if (-5)도 참(0이 아니므로) / else는 가장 가까운 위쪽 if와 결합 — 들여쓰기 의도와 무관.
🎯 빈출 조건문 흐름·else 결합 자리.
switch — Fall-through ·제어·매년 단골·
[정의] switch-case = 일치하는 case부터 break를 만날 때까지 모든 case를 줄줄이 실행한다. 이를 Fall-through라고 한다. case 값은 정수형 상수만(int·char), 실수·문자열 불가.
[코드]
int grade = 'B';
switch (grade) {
case 'A': printf("A\n"); /* break 없음! */
case 'B': printf("B\n"); /* 'B' 매칭 → 실행 */
case 'C': printf("C\n"); /* Fall-through → 줄줄이 */
default: printf("D\n");
}
/* 출력: B C D (세 줄!) */
[표] if vs switch
| 항목 | if-else if |
switch-case |
|---|---|---|
| 조건 형태 | 범위·복합 (a > 5 && b < 10) |
정확한 값 (a == 5) |
| 값 자료형 | 모든 자료형 | 정수형만 |
| break | 불필요 | 필수 (없으면 Fall-through) |
[코드] 삼항 연산자 — if-else를 한 줄로
int max = (a > b) ? a : b; /* a가 크면 a, 아니면 b */
💡 switch는 에스컬레이터 — 'B층'에 도착했는데 break(내림 버튼)가 없으면 C층·D층까지 올라간다.
🔑 암기 "switch case는 정수형 상수만 · break 없으면 Fall-through · 범위는 if / 정확한 값은 switch / 즉석은 ? :"
⚠️ 함정 "break 없어도 한 case만 실행" ❌(→ 줄줄이) / case에 실수·문자열 ❌.
🎯 빈출 Fall-through가 매년 1문제는 무조건.
PART F — 반복문
for · while · do-while ·제어·
[정의] 반복문 3형제. for=횟수가 정해짐, while=조건 충족까지, do-while=본문을 먼저 실행하고 조건을 나중에 검사해 최소 1회 보장.
[코드]
for (int i = 0; i < 5; i++) printf("%d ", i); /* 0 1 2 3 4 */
int i = 10;
do {
printf("%d ", i); /* 조건과 무관하게 한 번 실행! */
i++;
} while (i < 5); /* 출력: 10 — 조건 거짓이어도 본문 1회 */
[표] 3형제 비교
| 항목 | for |
while |
do-while |
|---|---|---|---|
| 언제 쓰나 | 횟수 정해짐 | 조건 충족까지 | 최소 1회 보장 |
| 조건 검사 | 본문 앞 | 본문 앞 | 본문 뒤 |
| 최소 실행 | 0회 가능 | 0회 가능 | 1회 보장 |
💡 for=횟수 마라톤(5바퀴) · while=비 그칠 때까지 산책 · do-while=일단 한 발 내딛고 비 오는지 확인.
🔑 암기 "for=횟수 / while=조건 / do-while=최소 1회. for 3요소 = 초기화·조건식·증감식"
⚠️ 함정 do-while은 조건이 처음부터 거짓이어도 본문 1회 실행 / for(;;)는 무한 루프(3요소 모두 생략 가능, ;은 필수).
🎯 빈출 do-while 최소 1회·for 3요소.
중첩 반복과 break · continue ·제어·
[정의] 중첩 반복 = 바깥 1번 돌 때 안쪽이 N번. 총 실행 = 바깥 × 안쪽. break=반복 완전 종료, continue=이번 회차만 건너뛰기.
[코드]
for (int i = 0; i < 10; i++) {
if (i == 5) break; /* i=5에서 즉시 종료 → 0 1 2 3 4 */
printf("%d ", i);
}
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) continue; /* 짝수면 건너뛰기 → 1 3 5 7 9 */
printf("%d ", i);
}
[표] break vs continue
| 항목 | break |
continue |
|---|---|---|
| 동작 | 반복 완전 종료 | 이번 회차만 건너뛰기 |
| 중첩에서 | 안쪽 루프 1개만 탈출 | 안쪽 루프만 건너뜀 |
| switch에서 | Fall-through 막기 | 사용 안 됨 |
💡 break는 극장에서 비상구로 완전 탈출(영화 안 봄), continue는 한 좌석 건너뛰고 옆에 앉기(영화는 계속).
🔑 암기 "중첩 = 바깥 × 안쪽 · break는 안쪽 루프만 탈출 / break 완전 종료 · continue 이번 회차만"
⚠️ 함정 중첩에서 break가 바깥 루프까지 한 번에 탈출 ❌(→ 안쪽 1개만).
🎯 빈출 break/continue 추적, 중첩 총 실행 횟수(2중 = O(N²)).
PART G — 변수 범위와 배열
변수 범위 — 전역 vs 지역 ·범위·
[정의] 전역 변수 = 함수 밖에 선언·모든 함수에서 사용·Data 영역 / 지역 변수 = 함수 안에 선언·그 함수 안에서만·Stack 영역. 같은 이름이면 지역이 전역을 가림(Shadowing).
[코드]
int x = 100; /* 전역 */
void test() {
int x = 50; /* 같은 이름 지역 — 지역이 우선! */
printf("%d\n", x); /* 50 */
}
int main() {
test(); /* 50 */
printf("%d\n", x); /* 100 — 함수 밖에서는 전역 */
}
[표] 전역 vs 지역
| 종류 | 선언 위치 | 사용 범위 | 메모리 영역 |
|---|---|---|---|
| 전역 | 함수 밖 | 모든 함수 | Data |
| 지역 | 함수 안 | 그 함수 안에서만 | Stack |
💡 전역은 거실의 가족 공용 TV, 지역은 내 방의 개인 노트북 — 방 문(함수)을 닫으면 노트북(지역)은 사라진다.
🔑 암기 "전역 = 거실 / 지역 = 내 방 · 같은 이름이면 지역이 우선(Shadowing)"
⚠️ 함정 "같은 이름이면 전역이 우선" ❌(→ 지역 우선).
🎯 빈출 범위·Shadowing 결과 예측.
static — 정적 변수 ·범위·시험 1순위·
[정의] static 변수 = 지역 변수처럼 함수 안에 선언되지만 함수가 끝나도 사라지지 않고 다음 호출 때 이전 값을 유지한다. 첫 호출 때 한 번만 초기화, Data 영역에 저장.
[코드]
void counter() {
int local = 0; /* 매번 0으로 초기화 */
static int stat = 0; /* 첫 호출만 0, 이후 유지 */
local++; stat++;
printf("local=%d, static=%d\n", local, stat);
}
/* counter() 3번 호출 →
local=1, static=1
local=1, static=2
local=1, static=3 ← static만 누적! */
[표] 지역 vs static
| 항목 | 지역 변수 | static 변수 |
|---|---|---|
| 생명주기 | 함수 호출~종료 | 프로그램 시작~종료 |
| 메모리 | Stack | Data (전역과 같음) |
| 초기화 | 매 호출마다 | 첫 호출 때 한 번만 |
💡 static은 내 방 안의 금고 — 방 문을 닫고 나가도 금고 안 물건은 그대로. 다음에 들어와 열면 그대로 있다.
🔑 암기 "static = 금고 · 첫 호출만 초기화 + 함수 끝나도 값 유지 + Data 영역"
⚠️ 함정 "static은 매 호출마다 초기화" ❌(→ 첫 호출 때만).
🎯 빈출 static 누적 추적이 매년. 저장 영역(지역=Stack / 전역·static=Data)은 40강에서 더 자세히.
배열과 sizeof ·배열·
[정의] 배열 = 같은 자료형의 데이터를 연속된 메모리에 N개 저장. 인덱스는 0부터 시작하고 마지막은 크기-1. 원소 개수 = sizeof(arr) / sizeof(arr[0]).
[코드]
int arr[5] = {10, 20, 30, 40, 50};
printf("%d\n", arr[0]); /* 10 — 첫 번째는 인덱스 0! */
printf("%d\n", arr[4]); /* 50 — 마지막은 크기-1 */
int len = sizeof(arr) / sizeof(arr[0]); /* 20 / 4 = 5 */
💡 C 배열의 인덱스는 달리기 트랙처럼 0번 레인부터 시작 — 크기 5짜리 배열의 마지막은 4번(5번 아님). sizeof(arr)는 전체 바이트(5×4=20), sizeof(arr[0])는 한 요소(4) → 나누면 원소 개수 5.
🔑 암기 "인덱스 0~크기-1 · 원소 개수 = sizeof(arr) / sizeof(arr[0])"
⚠️ 함정 "크기 5 배열의 마지막 인덱스는 5" ❌(→ 4) / "sizeof(arr)가 원소 개수" ❌(→ 바이트 크기).
🎯 빈출 인덱스·sizeof 길이 계산이 매 회차. 배열 이름 자체가 첫 요소의 주소(arr ≡ &arr[0])라는 성질은 40강 포인터에서 본격적으로 다룬다.
기출 다지기
[기출 1 출제] 다음 중 C언어 자료형과 크기(바이트)의 짝짓기로 옳지 않은 것은? (옳지 않은 것 고르기)
- ①
char— 1바이트 - ②
int— 4바이트 - ③
float— 4바이트 - ④
double— 4바이트
정답 및 해설 보기
정답: ④ — double은 8바이트다.
| 보기 | 자료형 | 크기 | 판정 |
|---|---|---|---|
| ① | char |
1 | O |
| ② | int |
4 | O |
| ③ | float |
4 | O |
| ④ | double |
8 | X |
float(4B)과 double(8B)을 바꿔치기하는 것이 매 회차 단골 패턴이다.
🔑 암기 ★자정실문★ + 1·2·4·8(char 1 · short 2 · int 4 · double 8)이면 짝짓기 즉답.
[기출 2 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
int a = 10, b = 3;
double c = a / b;
printf("%.2f\n", c);
- ① 3.00
- ② 3.33
- ③ 3.30
- ④ 컴파일 에러
정답 및 해설 보기
정답: ① 3.00
a, b 둘 다 int이므로 a / b는 정수 나눗셈 — 10 / 3 = 3(소수점 버림). 그 정수 3을 double c에 대입하면 c = 3.0, 출력은 3.00.
'double에 대입하니 3.33이 나오겠지'가 함정이다. 대입은 이미 정수가 된 후에 일어난다. 3.33을 얻으려면 (double)a / b처럼 한쪽을 실수로 캐스팅해야 한다.
🔑 암기 정수 ÷ 정수 = 정수(버림). 한쪽이라도 실수여야 실수 나눗셈.
[기출 3 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
int a = 5;
int b = a++ + ++a;
printf("%d %d\n", a, b);
- ① 7 11
- ② 7 12
- ③ 6 10
- ④ 8 12
정답 및 해설 보기
정답: ② 7 12
| 단계 | 동작 | a 값 |
|---|---|---|
| 시작 | a = 5 | 5 |
a++ |
5 사용 후 a → 6 | 6 |
++a |
a → 7 먼저 증가 후 7 사용 | 7 |
| 결과 | b = 5 + 7 = 12 | a=7, b=12 |
후위(a++) = 현재 값 사용 후 증가, 전위(++a) = 먼저 증가 후 사용. 이 두 줄만 잡으면 증감 문제는 끝이다.
🔑 암기 후위는 사용 후 증가 / 전위는 먼저 증가.
[기출 4 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
int n = 2;
switch (n) {
case 1: printf("A\n");
case 2: printf("B\n");
case 3: printf("C\n"); break;
case 4: printf("D\n");
default: printf("E\n");
}
- ① B
- ② B C
- ③ B C D E
- ④ A B C
정답 및 해설 보기
정답: ② B C
n=2이므로 case 2에서 매칭 → B 출력. break가 없어 case 3으로 Fall-through → C 출력. 여기서 break;를 만나 switch 종료. case 4와 default는 도달하지 못한다.
에스컬레이터 비유 그대로 — B층에서 타고 올라가다 C층에서 break(내림 버튼)를 눌러 내린 것.
🔑 암기 case 매칭 후 break를 만날 때까지 줄줄이(Fall-through).
[기출 5 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
int sum = 0;
for (int i = 1; i <= 5; i++) {
if (i == 3) continue;
if (i == 5) break;
sum += i;
}
printf("%d\n", sum);
- ① 6
- ② 7
- ③ 10
- ④ 15
정답 및 해설 보기
정답: ② 7
| i | 동작 | sum |
|---|---|---|
| 1 | sum += 1 | 1 |
| 2 | sum += 2 | 3 |
| 3 | continue — 건너뛰기 | 3 |
| 4 | sum += 4 | 7 |
| 5 | break — 종료 | 7 |
continue는 이번 회차만 건너뛰기(i=3일 때 sum += 3 안 됨), break는 완전 종료(i=5 이후 안 봄). 결과 1 + 2 + 4 = 7.
🔑 암기 continue는 건너뛰기 / break는 완전 종료.
[기출 6 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
void test() {
static int a = 10;
int b = 10;
a++; b++;
printf("%d %d\n", a, b);
}
int main() {
test(); test(); test();
return 0;
}
- ① 11 11 / 11 11 / 11 11
- ② 11 11 / 12 11 / 13 11
- ③ 11 11 / 12 12 / 13 13
- ④ 11 11 / 11 12 / 11 13
정답 및 해설 보기
정답: ② 11 11 / 12 11 / 13 11
| 호출 | static a | int b | 출력 |
|---|---|---|---|
| 1번째 | 첫 호출만 초기화 10 → a++ → 11 | 매번 10 → b++ → 11 | 11 11 |
| 2번째 | 이전 값 유지 11 → a++ → 12 | 매번 새로 10 → 11 | 12 11 |
| 3번째 | 12 → a++ → 13 | 10 → 11 | 13 11 |
static a는 금고(함수 나가도 보존), 지역 b는 매 호출마다 새로 받는 메모지.
🔑 암기 static = 첫 호출만 초기화 + 누적. 지역은 매 호출마다 새로.
[기출 7 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
int a = 5, b = 3, c = 2;
int result = a + b * c > 10 && c < 5;
printf("%d\n", result);
- ① 0
- ② 1
- ③ 11
- ④ 16
정답 및 해설 보기
정답: ② 1
| 단계 | 연산 | 결과 |
|---|---|---|
| ① 곱셈 | b * c = 6 |
5 + 6 > 10 && 2 < 5 |
| ② 덧셈 | 5 + 6 = 11 |
11 > 10 && 2 < 5 |
| ③ 비교 | 11 > 10 = 1, 2 < 5 = 1 |
1 && 1 |
| ④ 논리 | 1 && 1 = 1 |
1 |
| ⑤ 대입 | result = 1 |
출력 1 |
곱셈 > 덧셈 > 비교 > 논리 > 대입 — 5단계 사다리 순서대로 따라가면 답이 나온다.
🔑 암기 우선순위는 곱셈 > 덧셈 > 비교 > 논리 > 대입.
[기출 8 출제] 다음 C 코드의 실행 결과는? (코드 실행 결과 예측)
int arr[] = {10, 20, 30, 40, 50};
int len = sizeof(arr) / sizeof(arr[0]);
int sum = 0;
for (int i = 0; i < len; i++)
sum += arr[i];
printf("len=%d, sum=%d\n", len, sum);
- ① len=4, sum=100
- ② len=5, sum=150
- ③ len=20, sum=150
- ④ len=5, sum=100
정답 및 해설 보기
정답: ② len=5, sum=150
sizeof(arr) = 5 × 4(int) = 20바이트, sizeof(arr[0]) = 4바이트. 20 / 4 = 5(원소 개수). 인덱스 0~4로 5회 반복, 10 + 20 + 30 + 40 + 50 = 150.
'sizeof(arr) = 20이니까 len=20'이 함정 — sizeof는 바이트 단위라 한 요소 크기로 나눠야 원소 개수가 나온다.
🔑 암기 배열 원소 개수 = sizeof(arr) / sizeof(arr[0]) · 인덱스 0~크기-1.
한 장 요약
| 주제 | 암기·핵심 | 결정 카드 |
|---|---|---|
| C 정체성 | 1972 데니스 리치 · UNIX | 컴파일러 · 3세대 고급 · 절차적 / 시작점 main() |
| 자료형 4종 | ★자정실문★ | 정수 1·2·4·8 / 실수 float 4 · double 8 / 문자 char 1B / 문자열 char 배열 \0 |
| 정수 나눗셈 | 정수 ÷ 정수 = 버림 | 5/2=2 · (int)3.7=3 · 한쪽이라도 실수여야 2.5 |
| 입출력 | printf / scanf | %d %f %c %s / scanf는 & 필수 · double %lf |
| 연산자 7대 | ★전증감산논비대★ | 우선순위 곱셈 > 덧셈 > 비교 > 논리 > 대입 |
| 조건문 | if / switch / 삼항 | 범위는 if · 정확한 값은 switch(Fall-through) · 즉석은 ? : |
| 반복문 | for / while / do-while | for=횟수 · while=조건 · do-while=최소 1회 |
| 흐름 제어 | break / continue | break=완전 종료(안쪽만) · continue=이번 회차만 |
| 변수 범위 | 전역(Data) / 지역(Stack) | 같은 이름이면 지역 우선(Shadowing) |
| static | 금고 | 첫 호출만 초기화 + 함수 끝나도 유지 + Data |
| 배열 | 인덱스 0~크기-1 | 원소 개수 = sizeof(arr) / sizeof(arr[0]) |
| 함정 6쌍 (매년 2~3쌍 출제) | 정답 |
|---|---|
5/2 = 2.5 |
2 (정수 나눗셈 버림) |
scanf에 & 없어도 됨 |
& 필수 (배열 제외) |
| switch break 없으면 한 case만 | 줄줄이 (Fall-through) |
2 + 3 × 4 = 20 |
14 (곱셈 먼저) |
| static 매 호출 초기화 | 첫 호출만 초기화 |
arr[5] 마지막 인덱스 5 |
4 (0~크기-1) |
🎯 합격 한 끗: 39강은 ★자정실문★(자료형 4종 1·2·4·8)과 ★전증감산논비대★(연산자 7대 + 우선순위 사다리) 두 두음에, 위 함정 6쌍만 코드로 손에 들면 매 회차 1문항 이상을 안정적으로 가져온다. 깊이 파는 단원이 아니라 추적 한 글자가 정답을 가르는 영역 — 5/2=2, scanf &, Fall-through, 2+3*4=14, static 첫 호출만, 인덱스 0~크기-1 여섯 줄만 정확히 외워두면 4과목 최고 킬러 영역에서 합격선을 확보한다. 38강의 ★순반선★(순차·반복·선택)이 여기서 if·switch·for·while 코드로 회수됐고, 배열 이름이 곧 첫 요소의 주소(arr ≡ &arr[0])라는 성질과 static의 저장 영역(Data)은 40강 포인터와 함수에서 본격적으로 만난다.
