[C 시리즈 6편] 함수로 코드 나누고 재사용하는 법

English version

5편에서 조건문과 반복문으로 흐름을 바꾸는 방법을 익혔다면, 이제 그 흐름을 기능 단위로 묶을 차례입니다. 함수는 "입력 -> 처리 -> 출력" 패턴을 이름으로 감싸 재사용할 수 있게 해 줍니다. 이번 글에서는 함수 선언과 정의를 나누고, 매개변수와 반환값을 어떻게 설계하는지 살펴봅니다.

이번 글에서 새로 나오는 용어

  1. 함수 선언 (Function Declaration): 함수가 어떤 이름, 매개변수, 반환형을 갖는지 먼저 알려 주는 문장
  2. 함수 정의 (Function Definition): 실제 동작을 구현한 코드 블록
  3. 매개변수 (Parameter): 함수가 호출될 때 받는 입력 값 자리
  4. 반환값 (Return Value): 함수가 계산을 마치고 바깥으로 돌려주는 값
  5. 함수 원형 (Function Prototype): main 위쪽에 적어 컴파일러가 함수 정보를 미리 알게 하는 선언

핵심 개념

학습 메모

  • 소요 시간: 50~60분
  • 준비물: 조건문·반복문 예제를 편하게 수정할 수 있는 상태
  • 학습 목표: 함수 선언·정의·호출 구조를 이해하고, 매개변수와 반환값을 설계하기

함수는 반복되는 코드를 이름 붙여 묶는 도구입니다. 복잡한 흐름을 작은 이름표로 나누면 한 번만 쓰더라도 "무엇을 한다"는 설명을 이름에 담을 수 있어 읽기가 쉬워집니다. 함수는 아래 다섯 가지 요소를 가진다고 보면 됩니다.

  1. 반환형: 계산 결과의 자료형 (int, void, double 등)
  2. 함수 이름: print_line, calculate_total 같은 동사 기반 이름이 좋습니다.
  3. 매개변수 목록: 함수가 필요로 하는 입력 값들
  4. 본문: 중괄호로 감싸 실제 동작을 적는 부분
  5. return 문: 반환형이 void가 아니라면 반드시 값을 돌려줘야 합니다.

코드로 따라하기

가장 작은 함수 만들기

#include <stdio.h>

void print_separator(void) {
    printf("----------\n");
}

int main(void) {
    print_separator();
    printf("C 함수 학습 시작\n");
    print_separator();
    return 0;
}

print_separator는 반환값이 없으므로 void를 사용합니다. main 안에서 이름만 불러도 해당 코드가 실행됩니다. 이렇게 반복되는 출력 코드를 함수 하나로 묶으면 실수를 줄이고 의도를 분명하게 표현할 수 있습니다.

매개변수로 입력 받기

#include <stdio.h>

int add_two_numbers(int a, int b) {
    return a + b;
}

int main(void) {
    int result = add_two_numbers(12, 30);
    printf("결과: %d\n", result);
    return 0;
}

a, b는 함수 안에서만 의미가 있습니다. 호출할 때 add_two_numbers(12, 30)처럼 값을 넘기면, 그 순간에만 a, b가 채워지고 함수가 끝나면 사라집니다. 이 덕분에 같은 함수를 다양한 입력으로 반복해서 사용할 수 있습니다.

반환값으로 결과 돌려주기

#include <stdio.h>

double average_score(int sum, int count) {
    if (count == 0) {
        return 0.0;
    }
    return (double)sum / count;
}

int main(void) {
    double avg = average_score(273, 3);
    printf("평균: %.2f\n", avg);
    return 0;
}

반환형이 double이므로 return 문에서도 double 값을 돌려줘야 합니다. 매개변수와 반환형이 다르면 컴파일 단계에서 경고나 오류가 발생할 수 있으니, 타입을 맞추는 습관이 필요합니다.

함수 원형으로 선언과 정의 분리하기

#include <stdio.h>

double celsius_to_fahrenheit(double c); // 함수 원형

int main(void) {
    double result = celsius_to_fahrenheit(24.0);
    printf("섭씨 24도 = 화씨 %.1f\n", result);
    return 0;
}

double celsius_to_fahrenheit(double c) {
    return (c * 9.0 / 5.0) + 32.0;
}

함수 정의를 main 아래에 작성하고 싶다면, 위쪽에 함수 원형을 적어 컴파일러에게 미리 알려야 합니다. 이렇게 해야 컴파일러가 호출 시점에 매개변수 개수와 반환형을 점검할 수 있습니다. 나중에 여러 파일로 나눌 때는 이 원형이 헤더 파일로 옮겨갑니다.

실전 예시: 성적 요약 함수 묶기

#include <stdio.h>

int is_pass(int score) {
    return score >= 60;
}

void print_report(int score) {
    if (is_pass(score)) {
        printf("점수 %d: 합격\n", score);
    } else {
        printf("점수 %d: 보충 학습\n", score);
    }
}

int main(void) {
    print_report(85);
    print_report(42);
    print_report(73);
    return 0;
}

is_pass는 값을 판단해서 1 또는 0을 반환합니다. print_report는 그 결과를 활용해 메시지를 출력합니다. 이렇게 작은 함수들을 조합하면 조건문과 반복문이 더 읽기 쉬워집니다.

왜 중요한가

  • 함수는 반복되는 조건·반복 구조를 이름으로 묶어 버그를 줄입니다.
  • 매개변수와 반환값을 명확히 하면 테스트가 쉬워지고, 잘못된 입력을 방어하기 좋습니다.
  • 선언과 정의를 분리하는 습관은 이후 여러 .c 파일과 헤더 파일을 다룰 때 필수입니다.
  • 함수 단위로 사고하면 디버깅 시 "어느 기능에서 문제가 생겼는가"를 더 쉽게 좁힐 수 있습니다.

CodeSandbox로 이어서 실습하기

아래 샌드박스는 CodeSandbox의 Universal starter입니다. C는 터미널에서 직접 컴파일하고 다시 실행하는 흐름이 중요하니, 이번 글의 코드를 파일로 만들고 빌드-실행 사이클을 다시 따라가 보세요.

Live Practice

C Practice Sandbox

CodeSandbox

Run the starter project in CodeSandbox, compare it with the lesson code, and keep experimenting.

Universal starterCterminal
  1. starter를 fork한 뒤 hello.c 같은 실습 파일을 만든다
  2. 본문 코드를 붙여 넣고 clang 또는 gcc가 있으면 직접 컴파일한다
  3. 코드를 고친 뒤 다시 빌드하고 실행 결과를 비교한다

C는 브라우저 미리보기보다 터미널 빌드 흐름이 핵심입니다. Universal starter의 컴파일러 구성이 환경에 따라 다를 수 있으니, 먼저 clang이나 gcc 사용 가능 여부부터 확인하세요.

실습

  • 따라 하기: print_separator, add_two_numbers, average_score 함수를 직접 입력하고 출력 결과를 확인합니다.
  • 확장하기: 점수 배열을 받아 평균과 최고점을 반환하는 함수를 두 개 만들어 보고, main에서 호출 순서를 바꿔 봅니다.
  • 디버깅: 일부러 함수 원형을 지워 보고 어떤 컴파일 오류가 나는지 확인합니다.
  • 완료 기준: 함수 선언과 정의의 차이를 설명하고, 매개변수·반환값을 가진 함수를 직접 작성해 호출할 수 있으면 됩니다.

마무리

이번 글에서는 흐름 제어 코드를 함수로 묶는 방법을 정리했습니다. 함수는 이후 배열, 문자열, 포인터를 다룰 때도 중심축이 됩니다. 다음 글에서는 여러 값을 한꺼번에 저장하는 배열과 문자열을 통해 "데이터 묶음"을 다루는 법을 살펴봅니다.

💬 댓글

이 글에 대한 의견을 남겨주세요