6-1-라.return

인수가 호출원으로부터 전달되는 작업 대상이라면 리턴값은 함수가 호출원으로 돌려주는 작업 결과이다. 앞에서 이미 봤지만 함수가 결과를 리턴할 때는 return 문을 사용한다. return문의 기능은 다음 두 가지이다.

우선 가장 일반적인 기능은 함수의 결과값을 호출원으로 돌려주는 것이다. return 예약어 다음에 리턴하고자 하는 값을 써 준다. Max 함수의 경우 a, b값의 대소에 따라 return a나 return b 명령으로 a나 b의 값 중 하나를 리턴하며 Add 함수는 ttt와 ddd를 더한 결과값을 리턴한다.

함수는 자신에게 맡겨진 임무대로 계산을 수행하여 그 결과를 호출원으로 리턴하며 호출원에서는 함수가 리턴한 값을 함수의 결과값으로 취한다. 함수가 어떤 값을 리턴할 것인가는 함수의 타입으로 이미 정의되어 있으므로 미리 정해진 타입의 값을 리턴하면 된다. Max와 Add는 모두 정수형 값을 리턴하도록 정의되었다.

호출원에서는 타입만 맞다면 함수가 리턴하는 값을 곧바로 사용할 수 있다. 즉, int 타입이 올 수 있는 곳이라면 int 타입을 리턴하는 함수도 항상 올 수 있다. Max 함수는 정수값을 리턴하므로 m=Max(a,b) 구문으로 Max 함수가 리턴하는 값을 정수형 변수 m에 대입할 수 있으며 Add 함수가 리턴하는 정수값을 printf의 %d 서식과 대응시킬 수도 있다.

함수는 단 하나의 유일한 결과를 리턴하기 때문에 타입만 맞다면 수식내에서도 바로 사용할 수 있다. d=Add(Max(a,b),c) 식은 a와 b중 큰 값과 c를 더한 값을 d에 대입한다. Max가 리턴하는 값이 정수형이므로 이 함수의 호출 결과를 Add 함수의 첫 번째 인수로 사용할 수 있고 Add가 더한 값을 정수형 변수 d에 대입할 수 있다. 함수는 한 번에 하나의 리턴값만 돌려줄 수 있기 때문에 타입만 맞다면 수식내에서 함수를 바로 쓸 수 있는 것이다. 다음 함수 호출도 모두 적법하다.

 

gotoxy(Max(a,b),Add(c,d));

Add(Add(Add(Add(1,2),3),4),5);

두 번째로 return 문은 결과를 돌려주는 것 외에 함수를 강제 종료시키는 기능을 한다. 함수 실행중에 return문을 만나면 함수의 뒷부분이 남아있건 말건 무조건 함수를 종료하고 호출원으로 돌아가 버린다. return문이 함수의 결과값을 돌려주는 명령인데 결과값을 돌려 주는 시점이 함수의 임무가 끝난 시점이므로 더 이상 함수의 나머지 부분을 실행할 필요가 없다.

return문의 함수 강제 종료 기능은 인수의 유효성을 검사할 때 많이 사용된다. 다음 함수는 두 개의 실수를 전달받아 두 실수를 나누기 연산하여 그 결과를 리턴한다.

 

double div(double a, double b)

{

     if (b==0) {

          return 0;

     }

     return a/b;

}

 

a와 b의 나눗셈 결과는 a/b인데 만약 b가 0이라면 나눗셈을 할 수 없다. 그래서 a/b를 계산하기 전에 b의 값이 0인지 먼저 검사해보고 만약 b가 0이라면 나누기 연산을 할 필요도 없이 0을 리턴해 버린다. 무효한 인수로부터 치명적인 에러를 방지하기 위해 중간에 함수의 실행을 중단하는 것이다. 참고로 다음 코드는 위 함수의 코드와는 의미가 다르며 경고로 처리되는데 어떻게 다른지 연구해 보자.

 

double div(double a, double b)

{

     if (b!=0) {

          return a/b;

     }

}

 

문자열 출력 함수에서 출력 좌표가 음수인 경우도 정상적인 출력을 할 수 없다. 시간값을 넘겨주는 인수로 29시 87분이라는 값이 전달되었다든가 사람의 나이값으로 2397살 따위의 잘못된 값이 전달되었다면 함수가 정상적인 실행을 할 수 없으므로 중간에 return해야 한다. return문은 함수 내부의 어느 위치든지 올 수 있다. 단독으로도 사용할 수 있고 조건문 뒤에 올 수도 있고 다중 루프의 안쪽에 있을 수도 있다. 루프가 몇겹이든 상관하지 않고 return문은 함수를 강제로 종료한다.

main 함수에서 return 문이 사용되면 이것은 곧 프로그램을 끝내라는 명령이 된다. main 함수는 프로그램의 본체이기 때문에 이 함수를 종료하는 것은 곧 프로그램을 종료하는 것과 같다. 그래서 main 함수에서 return문은 exit(0)와 효과가 같다.

함수를 사용하는 조금 더 실용적인 예제를 만들어 보자. 다음 예제는 5장에서 만든 Dec2Hex 예제를 함수를 사용하여 다시 작성한 것인데 Dec2Hex 예제에서 10진수를 16진 문자로 바꾸는 코드가 두 번 사용되었으므로 반복을 방지하기 위해 이 기능을 함수로 따로 분리시키는 것이 좋다.

 

: Dec2Hex2

#include <Turboc.h>

 

char Dec2HexChar(int d)

{

     if (d >= 16) {

          return '?';

     }

     return d+'0'+(d>9)*7;

}

 

void main()

{

     int input;

 

     for (;;) {

          printf("0~255사이의 수를 입력하시오(끝낼 때 -1) : ");

          scanf("%d",&input);

          if (input == -1) {

              break;

          }

 

          printf("입력한 수의 16진 표기 = %c%c\n",

              Dec2HexChar(input >> 4),Dec2HexChar(input & 0xf));

     }

}

 

Dec2HexChar 함수는 정수값을 인수로 전달받아 이 값에 대응되는 16진 문자 하나를 찾아 주는데 d가 16이상일 경우, 즉 16진 문자 하나의 범위를 넘어설 경우는 에러를 의미하는 '?'를 리턴하도록 했다. main에서는 변경하고자 하는 정수값을 이 함수로 전달하기만 하면 대응되는 문자를 즉시 얻을 수 있고 char 타입을 리턴하므로 함수 호출문을 %c 서식과 곧바로 대응시킬 수도 있다.

이전 예제에서는 상하위 니블값인 hi, low가 두 번씩 사용되어 별도의 변수를 선언했지만 이제 함수의 인수로 넘겨줄 때 한 번만 사용하면 되므로 이 변수들은 불필요해졌다. 함수를 호출할 때 input값으로부터 곧바로 상하위 니블을 추출하여 인수로 넘기면 된다. 만약 다른 프로젝트에서 Dec2HexChar 함수가 또 필요하다면 이 함수를 복사해서 가져 가기만 하면 되므로 재활용하기도 훨씬 쉽다.