공든탑앱 열기

실기 C: 함수 호출·재귀·static 추적

정보처리기사 · 실기 준비와 코드 읽기 · 약 18분

쉽게 말하면

실기 C 문제는 프로그램을 주고 '출력이 뭔가요?'라고 물어요. 머릿속으로만 따라가면 꼭 한 군데서 틀려요. 그래서 종이에 변수 이름을 가로로 적고, 한 줄 실행할 때마다 바뀐 값을 아래로 적어 가는 추적표를 그려요. 특히 잘 틀리는 곳은 static 변수(함수가 끝나도 값이 남음), 포인터로 넘긴 값(원래 변수가 바뀜), 재귀(끝까지 내려갔다가 되돌아오며 계산), break 없는 switch(아래 case로 계속 내려감)예요.

시험용 정의

C 출력 문제는 추적표로 푼다: 변수를 열로 적고 문장이 실행될 때마다 값을 한 줄씩 적는다. 자주 나오는 함정: static 지역 변수는 프로그램 시작 때 한 번만 초기화되고 호출이 끝나도 값이 유지된다. 전역 변수는 모든 함수가 함께 쓴다. C의 함수 인자는 값에 의한 호출(복사)이라 함수 안에서 바꿔도 원래 변수는 그대로지만, 주소(포인터)를 넘기면 *p로 원래 변수를 바꿀 수 있다. 재귀는 종료 조건까지 내려간 뒤 돌아오면서 계산하므로, 호출을 한 줄씩 펼쳐 적는다. switch는 break가 없으면 아래 case를 계속 실행한다(낙하, fall-through). 정수끼리 나누면 몫만 남고(7 / 2 = 3), % 는 나머지다. i++는 쓰고 나서 증가, ++i는 증가하고 나서 쓴다. 비트 연산자 &(AND), |(OR), ^(XOR), ~(NOT), <<·>>(시프트)는 2진수로 바꿔 계산한다.

비유로 이해하기

추적표는 가계부와 같다. 머릿속으로 '대충 이 정도 남았겠지' 하면 틀리지만, 들어오고 나간 것을 한 줄씩 적으면 마지막 잔액이 정확히 나온다.

자세히

먼저 알아 둘 말

말뜻
추적표변수 값이 바뀌는 과정을 한 줄씩 적은 표
지역 변수함수 안에서 만들어져 함수가 끝나면 사라지는 변수
static 지역 변수함수 안에 있지만 값이 프로그램 끝까지 남는 변수. 초기화는 한 번만
값에 의한 호출인자 값을 복사해 넘김. 함수 안에서 바꿔도 원래 변수는 그대로
재귀함수가 자기 자신을 다시 부르는 것. 종료 조건이 꼭 있어야 한다
낙하 (fall-through)switch에서 break가 없어 다음 case까지 이어서 실행되는 것

예제 1: 추적표 그리기

int a = 1, b = 1, t;
for (int i = 0; i < 5; i++) {
    t = a + b;
    a = b;
    b = t;
}
printf("%d %d\n", a, b);   // 8 13
itab
시작-11
0212
1323
2535
3858
413813

i가 5가 되면 조건이 거짓이라 끝나요. 피보나치 수열을 만드는 코드예요.

예제 2: static·전역 변수와 주소 전달

int g = 10;                       // 전역 변수

void f(void) {
    static int s = 0;             // 한 번만 초기화
    int l = 0;                    // 매번 0
    s++; l++; g--;
    printf("%d %d %d\n", s, l, g);
}

void inc(int *p, int v) { *p += v; v += 100; }

int main(void) {
    f(); f(); f();                // 1 1 9 / 2 1 8 / 3 1 7
    int x = 5, y = 3;
    inc(&x, y);
    printf("%d %d\n", x, y);       // 8 3
}

x는 주소로 넘겨 원래 값이 바뀌고, y는 값으로 넘겨 함수 안에서 v를 바꿔도 그대로예요.

예제 3: 재귀 펼치기

int fact(int n) { return n <= 1 ? 1 : n * fact(n - 1); }
int fib(int n)  { return n < 2 ? n : fib(n - 1) + fib(n - 2); }
void p(int n) {
    if (n == 0) return;
    printf("%d", n);
    p(n - 1);
    printf("%d", n);
}
// fact(5) = 120, fib(7) = 13
// p(3) 출력: 321123

p(3)은 3을 찍고 p(2)로 내려가요. 2, 1을 찍고 p(0)에서 돌아오면서 1, 2, 3을 다시 찍어요. 내려갈 때와 돌아올 때 할 일을 나눠 적으면 쉬워요.

예제 4: 연산자 함정

식결과이유
7 / 2, 7 % 23, 1정수 나눗셈은 몫만, % 는 나머지
i = 5; a = i++; b = ++i;a = 5, b = 7i++는 쓰고 증가, ++i는 증가하고 씀
5 & 3, 5 | 3, 5 ^ 31, 7, 6101과 011을 비트마다 AND, OR, XOR
5 << 1, 5 >> 110, 2왼쪽 시프트는 × 2, 오른쪽은 ÷ 2(몫)
~5-6비트를 모두 뒤집으면 −(n + 1)

시험에 이렇게 나와요

출제기준 기반

확인 문제

Q1. void f(void) { static int s = 0; s++; printf("%d ", s); }를 세 번 부르면 출력은?

  1. 1 2 3
  2. 1 1 1
  3. 0 1 2
  4. 3 3 3
정답 보기

1번 1 2 3

static 지역 변수는 처음 한 번만 0으로 초기화되고, 함수가 끝나도 값이 남아요. 그래서 1, 2, 3으로 커져요. static이 없으면 매번 0에서 시작해 1 1 1.

Q2. int x = 5; void f(int v) { v = 10; } 에서 f(x); 뒤 x의 값은?

  1. 10
  2. 0
  3. 알 수 없음
  4. 5
정답 보기

4번 5

값에 의한 호출이라 v는 x의 복사본이에요. x를 바꾸려면 f(&x)로 주소를 넘기고 *v = 10으로 써야 해요.

Q3. int f(int n) { if (n == 0) return 0; return n % 10 + f(n / 10); }일 때 f(345)의 값은?

  1. 3
  2. 12
  3. 345
  4. 543
정답 보기

2번 12

끝자리를 하나씩 떼어 더해요. 5 + 4 + 3 + f(0) = 12.

Q4. switch (2) { case 1: s += 1; case 2: s += 2; case 3: s += 3; break; default: s += 4; } 실행 뒤 s는? (처음 s = 0)

  1. 2
  2. 5
  3. 6
  4. 9
정답 보기

2번 5

case 2부터 시작해 break가 없으니 case 3까지 내려가 2 + 3 = 5. break에서 멈춰 default는 실행하지 않아요.

Q5. 12 ^ 5의 값은? (^ 는 XOR)

  1. 4
  2. 9
  3. 13
  4. 17
정답 보기

2번 9

1100 XOR 0101 = 1001 = 9. 같은 비트는 0, 다른 비트는 1.

헷갈리기 쉬운 O·X

static 지역 변수는 함수를 부를 때마다 다시 초기화된다.

정답 보기

X 처음 한 번만 초기화되고 값이 계속 남아요.

C에서 배열을 함수에 넘기면 첫 칸의 주소가 넘어가서, 함수 안에서 배열 값을 바꾸면 원래 배열도 바뀐다.

정답 보기

O

i = 3; a = ++i; 를 실행하면 a는 3이다.

정답 보기

X ++i는 먼저 증가하고 값을 써서 a는 4예요.

함께 보면 좋은 개념