일부 프로그램에서는 어떤 함수의 내부에 또 다른 함수가 선언된 형태를 볼 수 있습니다. 이를 흔히 '중첩 함수(nested function)'라고 부르지만, 엄밀히 말하면 이것은 진정한 의미의 중첩 함수가 아닙니다. 이러한 구조는 '어휘적 범위(lexical scoping)'라고 하며, C 언어에서는 유효하지 않습니다.
그 이유는 C 컴파일러가 내부 함수의 올바른 메모리 위치에 접근할 수 없기 때문입니다. 또한 중첩 함수 정의는 바깥 블록의 지역 변수에는 접근할 수 없고, 오직 전역 변수만 사용할 수 있습니다. C 언어에는 지역(local)과 전역(global) 두 가지 스코프만 존재하므로, 중첩 함수의 실질적인 활용도는 매우 제한적입니다.
따라서 아래 예제처럼 함수 안에 함수를 정의하려고 시도하면 컴파일 오류가 발생합니다.
오류가 발생하는 예제
#include <stdio.h>
main(void) {
printf("Main Function");
int my_fun() {
printf("my_fun function");
// 첫 번째 함수 안에 또 다른 함수를 정의
int my_fun2() {
printf("my_fun2 is inner function");
}
}
my_fun2();
}실행 결과
text.c:(.text+0x1a): undefined reference to `my_fun2'
컴파일러가 내부에 정의된 my_fun2 함수를 찾지 못해 'undefined reference' 오류가 발생하는 것을 확인할 수 있습니다.
GCC 확장 기능으로 중첩 함수 사용하기
표준 C에서는 불가능하지만, GNU C 컴파일러(GCC)의 확장 기능을 활용하면 중첩 함수 선언이 허용됩니다. 방법은 간단합니다. 중첩 함수를 선언하기 전에 auto 키워드를 붙여주면 됩니다.
예제
#include <stdio.h>
main(void) {
auto int my_fun();
my_fun();
printf("Main Function\n");
int my_fun() {
printf("my_fun function\n");
}
printf("Done");
}실행 결과
my_fun function Main Function Done
이처럼 auto 키워드를 사용하면 GCC 환경에서 함수 내부에 함수를 정의하고 호출할 수 있습니다. 다만 이는 표준 C가 아닌 GCC 고유의 확장 기능이므로, 이식성(portability)이 중요한 프로젝트에서는 사용을 피하는 것이 좋습니다. 표준을 준수해야 하는 코드라면 함수 포인터나 구조체 등을 활용한 대안 설계를 권장합니다.