6-1-다.인수

인수(Parameter)는 호출원에서 함수에게 넘겨주는 작업 대상이라고 할 수 있다. 두 함수 사이의 정보 교환에 사용되므로 매개 변수(Argument)라고도 한다. Max 함수의 경우 두 정수값 중 큰 값을 선택하는 기능을 하므로 대상이 되는 두 정수값을 전달받아야 하며 그래서 int a, int b를 인수 목록에 적어 주었다. 다음은 여러 가지 함수의 인수 예이다.

 

(x,y) 위치에 점수 Score를 출력하는 함수 : PrintScore(int x, int y, int Score)

실수 x의 제곱근을 구하는 함수 : GetSqrt(double x)

문자열에서 공백의 개수를 조사하는 함수 : GetSpaceNum(char *str)

 

작업 대상을 따로 전달받을 필요가 없다면 인수를 전혀 사용하지 않을 수도 있다. 예를 들어 화면을 지우는 clrscr 함수는 어떤 동작을 할 것인지 이미 정의되어 있으며 화면을 지우는데 별다른 지시 사항이 없으므로 별도의 인수를 전달받지 않는다. 인수가 없는 함수는 인수 목록을 비워 두거나 아니면 인수를 받지 않는다는 것을 분명히 표시하기 위해 인수 목록에 void라고 적는다.

 

clrscr();

clrscr(void);

 

인수는 형식인수와 실인수로 구분되는데 함수의 인수 목록에 나타나는 인수를 형식 인수라고 하며 함수 호출부에서 함수와 함께 전달되는 인수를 실인수라고 한다. 영문으로 된 표준 문서에는 형식 인수를 Parameter로, 실인수를 Argument로 용어를 구분하고 있지만 여기서는 의미가 좀 더 분명한 형식 인수, 실인수라는 용어를 사용하기로 한다. Max 함수의 경우를 보자.

Max 함수의 인수 목록에 있는 int a, int b는 형식 인수이고 main 함수에서 Max 함수를 호출할 때 사용한 a, b는 실인수이다. 이 경우 형식인수와 실인수의 이름이 일치하는 것은 어디까지나 우연일 뿐이며 다른 이름을 가질 수도 있다. Max(i,j)로 이 함수를 호출할 수도 있고 Max(3,4)와 같이 상수값을 전달하는 것도 가능하다.

형식 인수는 호출원에서 전달한 실인수값을 잠시 저장하기 위한 임시 저장 장소이므로 어떤 이름이든지 사용해도 상관없다. 자신에게 전달된 인수값을 형식 인수에 잠시 대입해 놓고 함수 본체에서는 형식 인수로 호출원으로부터 전달된 실인수값을 읽기만 하면 된다. Max 함수는 다음과 같이 작성해도 완전히 동일하다.

 

int Max(int num1, int num2)

{

     if (num1 > num2) {

          return num1;

     } else {

          return num2;

     }

}

 

호출원에서 전달받은 값을 이 함수내에서 num1, num2로 부르겠다는 뜻이다. Max 함수가 이렇게 정의되어 있고 main 에서 Max(a,b)를 호출했다면 형식 인수 num1이 실인수 a의 값을 가지게 되고 형식인수 num2는 실인수 b의 값을 가지게 될 것이다. 인수 전달은 일종의 대입 연산이며 함수 호출 과정에서 a, b의 값이 num1, num2로 대입된다. Max 함수는 전달받은 형식인수값의 대소를 판단하여 더 큰 수를 리턴하기만 하면 된다. 다음 예제는 두 정수의 값을 더하는 함수 Add를 정의한 것이다.

 

: AddFunc

#include <Turboc.h>

 

int Add(int ttt, int ddd)

{

     return ttt+ddd;

}

 

void main()

{

     int a,b;

     a=3;

     b=4;

 

     printf("3+4=%d\n",Add(a,b));

     printf("5+6=%d\n",Add(5,6));

}

 

Add 함수는 두 개의 정수 ttt와 ddd를 인수로 전달받고 이 두 값의 합을 리턴한다. main에서는 Add(a,b)와 같이 실인수로 변수를 사용할 수도 있고 Add(5,6)과 같이 상수를 넘길 수도 있다. 실행 결과는 다음과 같다.

 

3+4=7

5+6=11

 

이 예제를 통해 형식 인수의 이름은 함수 내에서만 일치하면 되므로 아무래도 상관이 없다는 것을 알 수 있다. 그러나 아무리 문법적으로는 그렇더라도 함수를 사용하는 사람이 인수의 이름으로부터 의미를 쉽게 유추할 수 있도록 성의있게 이름을 붙이는 것이 좋다. gotoxy(int a, int b) 보다는 gotoxy(int x, int y)라는 이름이 훨씬 더 이해하기 쉽다.

함수가 받을 수 있는 인수의 개수에는 제한이 없으므로 인수 목록에 콤마로 구분하여 인수를 나열하기만 하면 된다. 예를 들어 정수형 변수 4개를 취하는 함수라면 다음과 같은 인수 목록을 가지게 될 것이다.

 

int func(int a, int b, int c, int d)

{ 본체 }

 

변수를 선언할 때 같은 타입은 int a,b,c,d; 형식으로 한꺼번에 선언할 수 있으므로 인수 목록을 다음과 같이 쓸 수 있을 것 같기도 하다.

 

int func(int a,b,c,d)

{ 본체 }

 

그러나 이런 형식은 허용되지 않는다. 대신 다음과 같이 쓰는 방법은 있는데 구형 C 컴파일러에서 흔히 쓰던 방법이다. C++에서는 이 형식을 지원하지 않지만 비주얼 C++도 소스 파일의 확장자가 C이면 이런 형식을 아직까지도 허용한다.

 

int func(a,b,c,d)

int a,b,c,d;

{ 본체 }

 

인수 목록에는 형식 인수의 이름만 적고 본체가 시작되기 전에 이 인수들의 타입을 밝히는 것이다. 여러 타입이 혼합되어 있을 때도 이 방식을 사용할 수 있다.

 

int func(a,b,c,d)

int a,b;

double c,d;

{ 본체 }

 

이 방식은 아주 옛날 ANSI C 표준이 제정되기 전의 클래식 C에서 쓰던 방식이라 요즘은 이런 형태의 인수 목록을 볼 기회가 거의 없을 것이다. 그러나 이런 식으로도 인수 목록을 쓸 수 있다는 것은 꼭 알아 두어야 한다. 왜냐하면 C의 베테랑들이 작성한 주옥같은 작품들을 분석하다보면 이런 인수 목록을 실제로 볼 수 있기 때문이다. 즉 과거의 소스를 읽기 위해 옛날 사람들이 사용하던 문법에 대해서도 약간은 알아 둘 필요가 있다.