C언어 함수 형식 그리고 재귀 함수
반응형

인수와 리턴값이 없는 함수

함수 단독으로 모든 입, 출력 기능을 포함한 함수입니다.

#include<stdio.h>

void greatNum();       // 함수 선언

int main()
{
    greatNum();        // 함수 호출
    return 0;
}

void greatNum()        // 함수 정의
{
    int i, j;
    printf("크기를 비교할 두 숫자를 입력하세요...");
    scanf("%d%d", &i, &j);
    if(i > j) {
        printf("큰 숫자는: %d", i);
    }
    else {
        printf("큰 숫자는: %d", j);
    }
}

위의 예제를 보시는 것과 같이 함수 호출 부로부터 아무런 입력값이 없이 함수내에서 모든 것을 처리합니다. 단순히 두 숫자를 사용자로부터 입력받아 비교하는 함수입니다.

인수는 없고 리턴값만 있는 함수

아래는 위의 예제를 리턴값이 있는 함수로 수정한 버전입니다.

#include<stdio.h>

int greatNum();       // 함수 선언

int main()
{
    int result;
    result = greatNum();        // 함수 호출
    printf("큰 숫자는: %d", result);
    return 0;
}

int greatNum()        // 함수 정의
{
    int i, j, greaterNum;
    printf("크기를 비교할 두 숫자를 입력하세요...");
    scanf("%d%d", &i, &j);
    if(i > j) {
        greaterNum = i;
    }
    else {
        greaterNum = j;
    }
    // 함수 호출부로 값을 리턴
    return greaterNum;
}

다른 점이라면 호출부분에서 리턴값을 받기 위해 result 변수를 선언하여 값을 저장합니다.

인수는 있고 리턴값이 없는 함수

아래는 똑같은 예제를 더 수정한 버전입니다. 리턴값을 없애고 인수로 즉 아규먼트로 두 개의 숫자를 전달하는 함수입니다.

#include<stdio.h>

void greatNum(int a, int b);       // 함수 선언

int main()
{
    int i, j;
    printf("크기를 비교할 두 숫자를 입력하세요...");
    scanf("%d%d", &i, &j);
    greatNum(i, j);        // 함수 호출
    return 0;
}

void greatNum(int x, int y)        // 함수 정의
{
    if(x > y) {
        printf("큰 숫자는: %d", x);
    }
    else {
        printf("큰 숫자는: %d", y);
    }
}

인수와 리턴값이 있는 함수

함수의 주목적은 재사용에 있습니다. 그러기 위해서는 함수 내에 최대한 외부 의존적인 코드가 없는 독립적인 코드로 작성돼야 합니다.  아래 예제는 이러한 점을 잘 나타내고 있습니다.

#include<stdio.h>

int greatNum(int a, int b);       // 함수 선언

int main()
{
    int i, j, result;
    printf("크기를 비교할 두 숫자를 입력하세요...");
    scanf("%d%d", &i, &j);
    result = greatNum(i, j); // 함수 호출
    printf("큰 숫자는: %d", result);
    return 0;
}

int greatNum(int x, int y)        // 함수 정의
{
    if(x > y) {
        return x;
    }
    else {
        return y;
    }
}

중첩 함수 (Nesting of Functions)

함수 내에서 다른 함수를 호출하는 경우입니다. 여러번 중첩해서 함수를 호출할 수 있지만, 무한 중첩으로 빠질 위험이 있으므로 주의해서 사용해야 합니다.

function1()
{
    // 함수1 코드 
    
    function2(); // 함수2 호출
    
    // 함수1 코드
}

만약 function2()에서 또 다시 function1() 함수를 호출할 경우 무한 중첩에 빠지게 되어 프로그램은 종료하지 못하게 됩니다.

재귀 함수 (Recursion Function)

재귀 함수란 호출한 함수에서 자기 자신을 다시 호출하는 것입니다. 이러한 방법은 중첩 함수의 특별한 케이스입니다. 또한 재귀 함수를 빠져나가는 코드 즉 if 문등을 사용하여 재귀적 호출을 멈추는 조건이 꼭 포함돼야 합니다. 그렇지 않으면 무한 중첩과 마찬가지로 프로그램은 종료하지 못하게 됩니다.

다음은 재귀 함수를 이용한 팩토리얼(Factorial)를 구하는 예제입니다.

#include<stdio.h>

int factorial(int x);       // 함수 선언

void main()
{
    int a, b;
    
    printf("숫자를 입력하세요...");
    scanf("%d", &a);
    b = factorial(a);       // 함수 호출
    printf("%d", b);
}

int factorial(int x) //함수 정의
{
    int r = 1;
    if(x == 1) 
        return 1;
    else 
        r = x*factorial(x-1);       // 자기 자신을 호출
    
    return r;
}

위 예제를 보시면 factorial() 함수 내에서 또다시 factorial()을 호출합니다. 여기서 많은 분들이 혼동하게 되는데 자기 자신을 호출한다는 것은 같은 함수이지만 메모리상에서 실행되는 순서를 보면 다른 영역을 할당하여 실행되게 됩니다.

위 그림은 재귀 함수 호출을 단편적으로 보여주고 있습니다. 결국 제일 마지막 호출에서 if(x==1)를 만나게 되고 결국 불린 모든 함수는 순차적으로 호출한 함수에 리턴되게 됩니다. 결국 main() 함수로 넘어와 결과 값을 출력합니다.

재귀함수에서 중요한 포인트는 위의 예제처럼 중첩함수를 빠져나갈 수 있는 조건을 넣어야 합니다.

<< 다음 혼자 공부하는 C언어 이전 >>
반응형