60.2 함수 선언과 정의 분리하기

hello 함수를 main 함수 아래에 작성하면 어떻게 될까요? 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

function_undefined_error.c

#include <stdio.h>

int main()
{
    hello();    // hello 함수를 찾을 수 없음. 컴파일 에러

    return 0;
}

void hello()    // 반환값이 없는 hello 함수 선언 및 정의
{
    printf("Hello, world!\n");    // Hello, world! 출력
}

컴파일 결과

function_undefined_error.c(5): warning C4013: 'hello'이(가) 정의되지 않았습니다. extern은 int형을 반환하는 것으로 간주합니다.
function_undefined_error.c(11): error C2371: 'hello' : 재정의. 기본 형식이 다릅니다.

hello 함수가 정의되지 않았다고 하면서 컴파일 경고와 에러가 발생합니다. 왜냐하면 C 언어 컴파일러는 위에서부터 아래로 소스 코드를 해석하는데 main 함수 부분에서는 hello 함수에 대한 정보가 없었기 때문입니다.

어떤 함수가 있다는 사실을 알려주려면 함수 선언(function declaration)을 해주어야 합니다. 함수 선언은 다음과 같이 반환값 자료형, 함수 이름, ( ) (괄호)순으로 적어주고 ; (세미콜론)을 붙입니다. 특히 여기서는 함수를 정의할 때와는 달리 { } (중괄호)를 사용하지 않습니다.

  • 반환값자료형 함수이름();

즉, 함수 형태만 선언하기에 이를 함수 원형(function prototype)이라 부릅니다.

다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

function_prototype.c

#include <stdio.h>

void hello();    // 반환값이 없는 hello 함수 원형 선언

int main()
{
    hello();    // hello 함수 호출

    return 0;
}

void hello()    // 반환값이 없는 hello 함수 정의
{
    printf("Hello, world!\n");    // Hello, world! 출력
}

main 함수 위에서 void hello();와 같이 반환값 자료형, 함수 이름, ( )을 적어준 뒤 세미콜론을 붙이면 hello 함수가 있다는 것을 알려줄 수 있습니다.

함수 선언이 된 상태에서는 main 함수 아래에서 hello 함수를 정의해주면 됩니다. 단, 함수 선언만 있고 정의가 없다면 링크 에러가 발생합니다.

참고 | 함수 원형과 함수 본체

함수 선언과 정의가 분리된 상태에서는 함수 선언 부분을 함수 원형(function prototype), 함수 정의(function definition) 부분을 함수 헤더(function header)와 함수 본체(function body)라고 부릅니다.

함수 선언

void hello(); // ← 함수 원형

함수 정의

void hello() // ← 함수 헤더
{
    printf("Hello, world!\n");
}
// ↑ 함수 본체

함수를 호출하는 부분 위에 함수가 정의되어 있고, 따로 함수 선언이 없을 때는 함수 정의와 선언이 동시에 이루어집니다.

#include <stdio.h>

void hello()    // 함수 정의와 선언이 동시에 이루어짐
{
    printf("Hello, world!\n");
}

int main()
{
    hello();    // hello 함수 호출

    return 0;
}

지금까지 함수에 대해 배웠는데 함수는 C 언어의 핵심이라 할 수 있습니다. 그러므로 시간을 두고 문법과 사용 방법을 정확히 익히는 것이 좋습니다.