함수 기초
지난 편에서는 char 배열로 문자열을 다루는 방법을 배웠습니다. 그런데 코드를 작성하다 보면 비슷한 작업을 여러 번 반복해서 수행해야 하는 경우가 많이 생깁니다. 예를 들어 두 수 중 큰 값을 찾는 코드나 특정 값을 검증하는 코드를 프로그램 곳곳에서 필요로 한다면, 그때마다 같은 코드를 복사해서 붙여 넣는 것은 비효율적이고 실수하기도 쉽습니다. 이럴 때 사용하는 것이 바로 오늘 배울 “함수”입니다.
함수란 무엇인가
함수는 특정 작업을 수행하는 코드 묶음에 이름을 붙여놓은 것입니다. 한 번 만들어두면 필요할 때마다 이름만 불러서(호출해서) 반복 사용할 수 있고, 코드의 가독성도 훨씬 좋아집니다. 사실 우리는 이미 함수를 사용해왔습니다. printf, scanf, strlen 같은 것들이 모두 C 표준 라이브러리에서 미리 만들어둔 함수입니다. 오늘은 이런 함수를 우리가 직접 만드는 방법을 배워보겠습니다.
함수의 기본 구조
함수는 크게 반환형, 함수 이름, 매개변수 목록, 함수 몸체(body)로 구성됩니다.
int add(int a, int b) {
int result = a + b;
return result;
}
여기서 각 부분의 의미는 다음과 같습니다.
int(반환형): 함수가 작업을 마치고 돌려줄 값의 자료형입니다. 아무 값도 돌려주지 않는다면void를 사용합니다.add(함수 이름): 이 함수를 호출할 때 사용할 이름입니다. 변수 이름처럼 의미를 알기 쉽게 짓는 것이 좋습니다.(int a, int b)(매개변수): 함수를 호출할 때 전달받는 값들입니다. 함수 내부에서는 이 값들을 마치 지역 변수처럼 사용할 수 있습니다.return result;: 계산한 값을 호출한 곳으로 돌려줍니다.return을 만나는 즉시 함수는 실행을 마치고 종료됩니다.
함수 선언과 정의, 그리고 호출
C언어는 기본적으로 코드를 위에서 아래로 읽으면서 처리하기 때문에, main 함수보다 아래에 함수를 만들어두면 컴파일러가 아직 그 함수를 모르는 상태에서 호출을 만나 오류가 날 수 있습니다. 이를 방지하기 위해 함수 원형(prototype)을 미리 선언해두는 것이 일반적인 방법입니다.
int add(int a, int b); // 함수 선언(원형)
int main(void) {
int sum = add(3, 5); // 함수 호출
printf("결과: %d\n", sum);
return 0;
}
int add(int a, int b) { // 함수 정의
return a + b;
}
함수 선언은 “이런 이름과 매개변수, 반환형을 가진 함수가 있다”는 것을 컴파일러에게 미리 알려주는 역할만 하고, 실제 동작 내용은 함수 정의 부분에 들어 있습니다. 함수 선언 끝에는 세미콜론을 붙이고, 함수 정의에는 중괄호로 몸체를 감싼다는 차이를 잘 기억해두어야 합니다.
예제 코드로 확인해보기
두 정수 중 더 큰 값을 찾아주는 함수와, 값을 돌려주지 않는 void 함수를 함께 사용해보겠습니다.
#include <stdio.h>
int getMax(int a, int b);
void printLine(void);
int main(void) {
int x = 12, y = 27;
printLine();
printf("x = %d, y = %d\n", x, y);
printf("더 큰 값: %d\n", getMax(x, y));
printLine();
return 0;
}
int getMax(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
void printLine(void) {
printf("--------------------\n");
}
코드 동작 설명 및 실행 결과
getMax함수는 매개변수로 받은a와b를 비교해서 더 큰 값을return으로 돌려줍니다.main함수의printf안에서getMax(x, y)를 호출하면, 그 자리에 함수가 돌려준 값이 그대로 들어가서 출력됩니다.printLine함수는 반환형이void이므로 아무 값도 돌려주지 않고, 단순히 구분선을 화면에 출력하는 역할만 합니다. 매개변수도void로 되어 있어 전달받는 값이 없다는 뜻입니다.- 함수 호출은
main함수 안에서 순서대로 이루어지며, 각 함수는 자신의 작업을 마치면 다시 호출했던 자리로 돌아옵니다. - 이 코드를
gcc functions.c -o functions로 컴파일하고 실행하면 다음과 같은 결과가 출력됩니다.
--------------------
x = 12, y = 27
더 큰 값: 27
--------------------
이처럼 반복해서 사용할 만한 기능을 함수로 미리 만들어두면, main 함수 안의 코드는 훨씬 짧고 읽기 편해집니다. 특히 getMax처럼 이름만 봐도 어떤 일을 하는지 짐작할 수 있게 지으면 나중에 코드를 다시 볼 때도 이해하기 쉽습니다.
핵심 요약
- 함수는 반복되는 작업을 이름을 가진 코드 묶음으로 만들어 재사용할 수 있게 해줍니다.
- 함수는 반환형, 이름, 매개변수, 몸체로 구성되며,
return문으로 값을 호출한 곳에 돌려줍니다. - 값을 돌려줄 필요가 없다면 반환형을
void로 지정합니다. main함수보다 뒤에 정의되는 함수는 함수 원형을 미리 선언해두어야 컴파일 오류 없이 호출할 수 있습니다.
다음 편에서는 함수를 좀 더 깊이 파고들어 “함수 심화 (재귀, 스코프, 파일 분리)”를 주제로, 함수가 자기 자신을 호출하는 재귀 호출과 변수의 유효 범위, 그리고 여러 파일로 코드를 나누는 방법까지 함께 알아보겠습니다.