52. 함수 개요

소프트웨어를 만들 때 가장 많은 비용이 들어가는 것이 유지 보수 비용이라는 연구 결과가 계속 나오고 있어요.
그리고 점점 유지 보수 비용이 차지하는 비율도 높아지고 있답니다.

프로그램을 제작할 때 유지 보수 비용을 줄이는 여러 가지 방법이 있는데 그 중에 하나가 재사용성을 높이는 것이죠.
여러 프로그램에서 공통으로 사용할 수 있는 것들을 라이브러리로 만들어서 필요할 때 추가하여 사용하는 거예요.
여러 개의 컴포넌트(Component, 부품)로 만들고 필요한 부품을 결합하여 프로그램을 만들어서 재사용성을 높이기도 해요.

그리고 프로그래밍할 때 재사용성을 높이는 기본은 함수를 만들어 사용하는 것이예요.
대부분의 프로그래밍 언어에서는 알고리즘이 같을 때 함수를 만들어 필요할 때 호출하여 사용하는 문법을 제공한답니다.

이번 장에서는 함수가 무엇인지 간단히 알아보고 간단한 알고리즘을 함수로 만드는 실습을 할거예요.
함수를 만드는 실습에서는 작성할 함수의 알고리즘을 파악하는 작업부터 시작하죠.
그리고 함수 이름을 정하고 결과에 영향을 주는 인자를 입력 매개변수 리스트로 정의하고 결과 형식을 약속해요.
그러고 나서 테스트 로직을 작성한 후에 함수 내부를 구현할 거예요.

컴퓨터 프로그램에서 함수는 특정 작업을 수행하는 코드의 집합이예요.
결국 컴퓨터 프로그램이 컴퓨터가 수행할 코드의 집합이므로 단위 함수들의 집합이라고 얘기할 수도 있겠죠.
물론 컴퓨터 프로그램은 수행할 코드 외에도 관리해야 할 데이터도 있어요.
따라서  “함수들의 집합이 컴퓨터 프로그램이다.”라고 말하는 것은 정확한 표현은 아니겠죠.
하지만 그만큼 함수가 차지하는 비중이 크다는 것을 말하는 거예요.

C언어 함수 문법에는 함수에서 해야 할 코드를 정의하는 함수 정의문과 작성한 함수를 호출하여 사용하는 함수 호출문, 함수 수행에 필요한 입력 매개변수 리스트와 리턴 형식을 컴파일러에게 알려주는 함수 선언문이 있어요.

◈ 함수 선언문, 정의문, 호출문

#include <stdio.h>
int Add(int a, int b); //함수 선언문
int main() //main 함수 정의문
{
    int re = 0;
    re = Add(2,3); //Add 함수 호출문
    printf("re:%d\n",re); //printf 함수 호출문
}
int Add(int a, int b)//Add 함수 정의문
{
    return a+b;
}

함수를 만들 때는 함수의 이름과 함수 수행에 필요한 입력 매개변수 리스트, 함수 수행 후에 호출한 곳으로 전달할 반환 형식과 함수에서 수행할 코드를 정의해요.

함수 이름은 호출하여 사용할 개발자가 이해하기 쉽게 함수에서 수행하는 기능이 무엇인지 알기 쉬운 동사로 정의하세요. 그리고 C 언어로 프로그램을 작성할 때는 같은 이름을 갖는 함수를 중복해서 정의할 수 없어요.

입력 매개변수 리스트는 함수를 수행하기 위해 호출하는 곳에서 전달하는 인자예요.
인자에 따라 결과에 영향을 주는 인수들이죠.
만약 두 수를 더하는 함수에서는 호출하는 곳에서 두 개의 수를 전달해야 계산할 수 있어요.
이 때 호출하는 곳에서 전달한 인자를 받기 위해 선언하는 것을 입력 매개변수 리스트라 말해요.
C언어에서 입력 매개변수 리스트는 0개에서 31까지 전달할 수 있어요.
반환 형식은 함수에서 수행할 결과를 호출한 곳에 전달할 값의 형식이예요.
함수에서 호출한 곳으로 반환할 수 있는 값은 최대 1개랍니다.

함수의 이름과 입력 매개변수 리스트, 반환 형식을 합쳐서 함수 원형이라고 불러요.
함수 원형은 함수를 정의하는 곳과 사용하는 곳과의 약속이예요.
호출하는 곳에서는 함수 선언문이 필요하고 함수 원형에 맞게 호출해서 사용해요.
보통 함수 선언문을 헤더에 작성하여 사용하는 곳에서 헤더 파일만 포함하면 사용할 수 있게 만들어요.

함수 정의문은 반환 형식과 함수 이름을 명시하고 지시 연산자 ( ) 안에 입력 매개변수 리스트를 콤마로 구분하여 열거하죠.
그리고 블록을 지정하여 블록 내부에 수행할 코드를 작성해요.
함수는 함수의 종료 블록을 만나거나 return 문을 만나면 수행이 끝나요.
반환 형식이 있으면 return 뒤에 전달할 값의 표현식을 작성하여 전달하죠.

반환 형식함수 이름 (입력 매개 변수 리스트)
{
    [수행할 코드]
}

int Add(int a,int b)//함수 정의문
{
    return a+b;
}

함수 선언문은 함수 정의문에 작성한 함수 원형을 컴파일러에게 알려주는 구문이예요.
컴파일러는 함수 호출문을 만나면 정의한 함수의 원형에 맞게 사용하는지 확인해요.
만약 함수를 사용하는 호출문이 함수 정의문보다 앞에 있으면 컴파일러는 맞게 작성하였는지 확인할 수 없어요.

반환 형식   함수 이름 (입력 매개 변수 리스트);
int Add(int a,int b);//함수 선언문
함수 호출문은 만들어진 함수를 필요할 때 사용하는 구문이예요.
함수를 호출할 때는 함수 원형에 맞게 입력 인자를 전달해야겠죠.
호출하는 곳에서 반환 값을 사용하는 것은 선택 사항이예요.

int i = 3, j=4;
int re = 0;
re = Add(i,j);//함수 호출문
printf("Test 1: %d + %d = %d\n",i, j, re);
re = Add(2,6);//함수 호출문
printf("Test 2: %d + %d = %d\n",2, 6, re);

◈ 두 수를 더하는 함수 선언문, 정의문, 호출문

#include <stdio.h>
int Add(int a,int b);//함수 선언문
int main()
{
    int i = 3, j=4;
    int re = 0;
    re = Add(i,j);//함수 호출문
    printf("Test 1: %d + %d = %d\n",i, j, re);
    re = Add(2,6);//함수 호출문
    printf("Test 2: %d + %d = %d\n",2, 6, re);
    return 0;
}
int Add(int a,int b)//함수 정의문
{
    return a+b;
}

◈ 실행결과

Test 1: 3 + 4 = 7
Test 2: 2 + 6 = 8
 

그리고 C언어로 함수를 작성할 때 함수 내부에서 값을 기억할 필요가 있으면 변수를 선언할 수 있어요.

특정 범위 내의 정수 합계를 구하는 함수를 예로 들어 볼게요.
함수 이름은 CalculateSum이라 가정할게요.

특정 범위 내의 정수 합계를 구하려면 호출하는 곳에서 범위의 시작 값과 범위의 끝 값을 전달해야겠죠.
그리고 수행 결과로 합계를 반환해야겠죠.
따라서 함수의 원형은 다음과 같이 결정하면 적당해요.

int CalculateSum(int begin, int end);

합계를 기억하기 위한 변수와 반복문에서 사용할 카운터 변수가 필요해요.

int sum = 0; //합계
int lcnt = 0; //반복문의 루프 카운터

함수 내부에서는 시작 값에서 끝 값 사이의 합계를 계산하기 위해 반복문이 필요하겠죠.
반복문에서는 초기값을 시작 값으로 하고 끝 값보다 작거나 같을 때까지 1씩 증가하면서 합계에 더하세요.

for( lcnt = begin; lcnt <= end; lcnt++)
{
    sum += lcnt;
}

마지막으로 더한 합계를 반환하세요.

return sum;//결과 반환

◈ 특정 범위 내의 정수 합계를 구하는 함수

#include <stdio.h>
int CalculateSum(int begin, int end);//함수 선언문
 
int main()
{
    int i = 1;
    int j = 100;
    int re = 0;
 
    re = CalculateSum(i,j); //함수 호출문
    printf("Sum(%d ~ %d) : %d\n", i, j, re);
 
    re = CalculateSum(5,100); //함수 호출문
    printf("Sum(%d ~ %d) : %d\n", 5, 100, re);
    return 0;
}
int CalculateSum(int begin, int end) //함수 정의문
{
    int sum = 0; //합계
    int lcnt = 0; //반복문의 루프 카운터
    for( lcnt = begin; lcnt <= end; lcnt++)
    {
        sum += lcnt;
    }
    return sum;//결과 반환
}

◈ 실행결과

Sum(1 ~ 100) : 5050
Sum(5 ~ 100) : 5040

◈ 기본 연습 (정답 바로가기)
1. 두 개의 정수를 입력 매개변수로 전달받아 큰 수를 반환하는 함수를 작성하시오.
그리고 작성한 함수를 이용해서 2, 9 중에 큰 수를 출력하시오.

2. 하나의 정수를 입력 매개변수로 전달받아 홀수일 때는 0을 반환하고 짝수일 때는 1을 반환하는 함수를 작성하시오.
그리고 작성한 함수를 이용해서 1~10 사이에 몇 개의 짝수가 있는지 출력하시오.

3. 하나의 정수를 입력 매개변수로 전달받아 소수일 때는 1을 반환하고 그렇지 않을 때는 0을 반환하는 함수를 작성하시오.
여기서 소수란 1과 자기 자신만을 약수로 갖는 수를 말합니다.
그리고 작성한 함수를 이용해서 1~100 사이에 몇 개의 소수가 있는지 출력하시오.

4. 두 개의 정수를 입력 매개변수로 전달받아 최소 공배수를 구하는 함수를 작성하시오.

5. 두 개의 정수를 입력 매개변수로 전달받아 최대 공약수를 구하는 함수를 작성하시오.