함수 호출

함수 호출 (Function calls)

함수 호출은 식의 일부예요(확장 문법을 쓰면 문장이 될 수도 있지만). 함수 호출은 다음과 같이 구성돼요.

출처: Free Pascal Reference - Function calls

본문

variable reference는 프로시저 타입 변수 참조여야 해요. 메서드 지정자(method designator)는 오직 객체의 메서드 안에서만 쓸 수 있고, 한정 메서드 지정자(qualified method designator)는 객체 메서드 밖에서도 쓸 수 있어요.

호출되는 함수는, 선언된 매개변수 목록이 실제 매개변수 목록과 일치하는 함수예요. 이는 다음을 의미해요.

  • 실제 매개변수의 개수는 선언된 매개변수의 개수와 같아야 해요(기본 매개변수 값을 쓰는 경우는 예외).
  • 매개변수의 타입은 서로 호환되어야 해요. 변수 참조 매개변수(var reference parameter)의 경우에는 타입이 정확히 같아야 해요.

일치하는 함수를 찾지 못하면 컴파일러는 오류를 생성해요. 어떤 오류가 나는지는, 무엇보다도 함수가 오버로드되었는지(즉 이름은 같고 매개변수 목록이 다른 함수가 여러 개 있는지)에 따라 달라져요.

컴파일러가 식 안에서 함수 호출을 실행하지 않는 경우도 있어요. 프로시저 타입 변수에 값을 대입할 때가 그 예인데, Delphi나 Turbo Pascal 모드에서 다음 예시처럼 동작해요.

Type
  FuncType = Function: Integer;
Var A : Integer;
Function AddOne : Integer;
begin
  A := A+1;
  AddOne := A;
end;
Var F : FuncType;
    N : Integer;
begin
  A := 0;
  F := AddOne; { Assign AddOne to F, Don't call AddOne}
  N := AddOne; { N := 1 !!}
end.

위 목록에서 F에 대한 대입은 함수 AddOne을 호출하지 않아요. 하지만 N에 대한 대입은 AddOne을 호출해요.

때로는 호출을 원하는 경우가 있어요(예를 들어 재귀에서). 그럴 땐 함수 이름에 괄호를 붙여 호출을 강제할 수 있어요.

function rd : char;

var
  c : char;

begin
  read(c);
  if (c='\') then
    c:=rd();
  rd:=c;
end;

var ch : char;

begin
   ch:=rd;
   writeln(ch);
end.

위 코드는 문자를 읽고 출력해요. 입력이 백슬래시면 두 번째 문자를 읽어요.

이 문법에는 다음과 같은 구성이 문제가 될 수 있어요.

If F = AddOne Then
  DoSomethingHorrible;

컴파일러는 FAddOne의 주소를 비교해야 할까요, 아니면 두 함수를 모두 호출해서 그 결과를 비교해야 할까요? fpcobjfpc 모드에서는 프로시저 변수를 포인터와 동등한 것으로 간주해서 해결해요. 그래서 컴파일러는 타입 불일치 오류를 내요. AddOne이 정수 결과를 반환하는 함수 호출로 간주되는데, F는 포인터이기 때문이에요.

그렇다면 FAddOne 함수를 가리키는지는 어떻게 확인할까요? 이때는 주소 연산자 @를 사용하면 돼요.

If F = @AddOne Then
  WriteLn ('Functions are equal');

불리언 식의 왼쪽은 주소예요. 오른쪽도 주소죠. 그래서 컴파일러는 두 주소를 비교해요. 두 함수가 반환하는 값을 비교하려면 어떻게 할까요? 빈 매개변수 목록을 추가하면 돼요.

  If F()=Addone then
    WriteLn ('Functions return same values ');

마지막 이 동작은 Delphi 문법과 호환되지 않는다는 점을 유의하세요. Delphi 모드를 켜면 Delphi 문법을 쓸 수 있어요.

더 알아보기

  • 함수 호출이 식에서 어떻게 위치하는지는 식 문법 섹션에서 다뤄요.
  • 주소 연산자 @에 대한 자세한 내용은 @ 연산자 섹션에서 확인할 수 있어요.