C 언어 | 함수 | 함수 만들기

반복되는 처리는 함수로서 부품화할 수 있다.

특정 처리를 함수에 정리한다

지금까지 프로그램은 main() 함수에 작성해 왔다. 처음에 설명했듯이 main() 함수는 프로그램이 실행될 때에 최초에 호출되는 애플리케이션 진입점을 나타내는 특수한 함수이다. 우리는 필요한 경우 main() 이외의 함수를 만들 수 있다. 지금까지는 표준 함수로 정해져 있는 printf()와 scanf() 등의 함수를 사용하여 왔는데, 이러한 일부 기능을 정리한 함수를 직접 만들 수 있는 것이다.

프로그램에서 여러번 사용되는 처리 함수로 정리하여, 동일한 코드를 여러번 작성하는 번거로움에서 해방되어 프로그램 전체에 정합성을 갖게 할 수 있다. 이는 응용 프로그램의 설계에 있어서 매우 중요한 것이다. 처음에 약간 설명했지만, 함수를 정의하려면 다음과 같이 설명한다.

함수의 정의

반환자료형 함수명 (매개 변수 목록) {
  문장
  ...
}

기본적인 작성법은 main() 함수와 동일하다. 함수명은 변수와 동일하게 C 언어의 명명 규칙을 따르고 있으면 자유롭게 지정할 수 있다. 함수의 기능을 나타내어 알기 쉽게 의미있는 이름으로하는 것이 바람직하다. 반환 값과 매개 변수 목록은 “파라미터와 반환 값"에서 자세히 설명하겠지만, 이것들을 이용하면 함수간에 데이터를 교환할 수 있다. 이 장에서는 우선 함수는 다음과 같이 정의한다.

void 함수명() { ... }

이 함수는 값을 받지 않고 값을 돌려주지 않는 것을 나타낸다. 반환 값의 자료형으로 지정하는 void는 함수가 값을 반환하지 않는 것을 의미한다. 값을 반환하지 않는 함수는 return 키워드 값을 반환할 수 없다. 함수를 호출할 때는 printf()와 같은 표준 함수처럼 호출할 수 있다.

함수명();

한번 만든 함수는 여러번 호출할 수 있기 때문에, 프로그램의 재사용이 가능하다. 다음의 프로그램은 새로운 함수 Function()를 정의하고 main() 함수에서 이것을 호출하여 사용하고 있다.

코드1

#include <stdio.h>

void Function() {
 printf("Kitty on your lap\n");
}

int main() {
  Function();
 Function();
 return 0;
}

Function() 함수는 printf() 함수를 호출하여 화면에 문자를 표시하는 간단한 처리를 수행한다. main() 함수에서 Function() 함수를 두번 호출한다. 그 결과, 화면에는 “Kitty on your lap"이라는 문자가 두 줄에 걸쳐 표시된다. 그러나 함수는 사용되는 함수보다 먼저 기술해야 합니다. 코드1을 보고 알 수 있듯이, Function() 함수는 이를 호출하는 main() 함수보다 이전에 정의되어 있다.

함수를 호출하기 전에 정의하거나 선언해야 컴파일러가 반환형과 매개 변수 형식을 확인할 수 있다. 선언되지 않은 함수를 호출하는 방식은 오래된 C 문법에 해당하며, 현재의 C 표준에서는 허용되지 않는다.

예를 들어, 다음 프로그램은 Function1()는 문제없이 호출할 수 있지만 Function2()는 오류이다.

int main() {
 Function1();
  Function2(); /*형식 불일치 오류*/
}
int Function1() {
  return 0;
}
void Function2() {}

현재의 C 표준에서는 Function1()과 Function2() 모두 선언 없이 먼저 호출할 수 없다. 함수를 호출하기 전에 정의하거나 함수 원형을 선언해야 한다.

코드1의 흐름을 따르면, 먼저 main() 함수가 실행되고 Function() 함수가 호출된다. 함수가 호출되면 프로그램은 그 함수에 제어를 이동시킨다. 코드1의 경우 Function() 함수의 본체에 제어가 이동하게 된다. Function() 함수의 처리가 완료되면, 프로그램은 함수를 호출한 원래 위치에 제어를 리턴한다. 이 경우는 main() 함수로 돌아 오게 된다.

그림1 - 함수의 호출과 복귀

함수의 호출과 복귀

함수를 호출하면 함수의 처리가 완료되면 제어가 함수를 호출한 원래의 위치로 돌아오기 때문에 프로그램의 흐름은 결국 main() 함수로 돌아간다.

void 형의 반환 값을 갖는 함수는 값을 돌려 줄 필요가 없기 때문에 return 문을 생략할 수 있다. main() 함수는 int 형의 종료 코드를 시스템에 반환해야 하므로 return 문을 사용하여 값을 반환하지만 Function() 함수는 return 문을 사용하지 않는다. 그러나 다음과 같이 명시적으로 return 문을 사용하여 함수를 종료 할 수 있다. 그러나 값은 반환시키지 않기 때문에 식을 지정할 수는 없다.

void Function() {
  printf("Kitty on your lap\n");
 return;
}

특정 위치에서 함수를 끝내고 싶다면, return 문을 사용하여 제어를 반환할 수 있다.

함수는 몇번이나 겹쳐서 호출할 수 있다. main() 함수가 Function1() 함수를 호출하고, Function1() 함수가 Function2() 함수를 호출 …… 등등 함수에서 다른 함수를 여러번 호출해도 함수는 자신을 호출한 곳으로 제어를 되돌리는 성질이 있으므로 반드시 최상위 제어, 즉 main() 함수로 복귀한다.

코드2

#include <stdio.h>

void Function2() {
 printf("Function2() : return\n");
}

void Function1() {
 printf("Function1() : Call Function2()\n");
  Function2();
  printf("Function1() : return\n");
}

int main() {
 printf("main() : Call Function1()\n");
 Function1();
  printf("main() : return\n");

 return 0;
}

코드2는 Function1() 함수에서 Function2() 함수를 호출한다. 이 프로그램은 제어의 흐름을 시각적으로 확인할 수 있도록 하기 위해, 각 함수는 자신의 함수명과 처리를 화면에 표시한다.

프로그램은 먼저 main() 함수에서 Function1() 함수를 호출하여 Function1() 함수는 Function2() 함수를 호출한다. Function2() 함수는 즉시 제어를 반환하기 때문에 Function1() 함수에 제어가 돌아간다. 그리고 Function1() 함수를 종료하고, 마지막으로 main() 함수에 복귀하고 있는 것을 확인할 수 있다. 표시된 결과를 보면 프로그램이 어떤 순서로 실행되고 있는지 이해할 수 있다.