본문 바로가기
프로그래밍언어론

[프로그래밍언어론] 25. 매개변수 전달(Parameter Passing)

by 파스텔코랄 2023. 10. 17.

매개변수 전달(Parameter Passing)

  • 매개변수 전달은 하위 프로그램이 프로그램의 다른 부분과 통신하는 방법이다.
  • 서브프로그램의 관점에서는 세 가지 종류의 매개변수를 고려할 수 있다.
    • IN 매개변수 : caller에서 callee로 통신
    • OUT 매개변수 : callee에서 caller로 통신
    • IN/OUT 매개변수 : 양방향 통신

 

  • 형식 매개변수(Formal parameters) : 함수의 선언에 나타나는 매개변수
  • 실제 매개변수(Actual parameters) : =인수(arguments), 함수 호출에서 함수에 전달되는 것

 


 

Call by Value

  • IN 매개변수에 해당하는 모드
  • 실제 매개변수(인수)는 표현식일 수 있다.
    • 호출 시 실제 매개변수가 계산되고 해당 리턴값(r-value)형식 매개변수와 연결된다.
    • 함수가 종료되면 형식 매개변수삭제되므로 값이 손실된다.
  • Call by value는 가장 간단하고 인기 있는 모드이다.
    • C와 Java에서 유일한 매개변수 전달 모드이다.

 


 

Call by Reference

  • 이 모드에서는 매개변수를 입력과 출력(IN/OUT) 모두 사용할 수 있다.
  • 실제 매개변수는 메모리를 참고하는 값(l-value)이 있는 표현식이어야 한다.
  • 함수가 호출되면 실제 매개변수의 l-value가 형식 매개변수와 연관된다. : aliasing

 

  • C++
class MyObject{
public:
    int val;
};

void func(MyObject& obj) {
    MyObject y;
    y.val = 10;
    obj = y;
}

int main()
{
    MyObject x;
    x.val = 1;
    func(x);
    cout << x.val;
}
  • 결과 : 10

 

  • Java에는 Call by Reference가 없다.
  • 변수 모델은 참조 모델이지만 매개변수 전달 자체는 Call by Reference이 아니다.

 

class A {
    int n;
}

void swap (A a1, A a2) {
    int tmp = a1.n;
    a1.n = a2.n;
    a2.n = tmp; //call by ref 시뮬레이션

    A tmp2 = a1;
    a1 = a2;
    a2 = tmp2; //What happens?
}


int main()
{
    A x;
    A y;
    swap(x, y);
}



  • 유형 A의 객체에 대한 두 참조가 복사되어 swap()에 전달된다.
  • 참조 모델(a1.n)을 사용하여 멤버 변수의 값을 변경할 수 있다.
  • 하지만 실제로 두 변수 x와 y를 바꿀 수는 없다.

 


 

Call by Constant

  • 함수 본문에서 매개변수를 수정하지 않은 경우
    • Call by Reference을 사용하여 구현하는 동안 Call by Value의 의미를 유지한다.
    • 매개변수는 읽기 전용으로 간주된다.

 

  • C++
void func(const MyObject& obj);

 


 

Call by Result

  • output 전용 통신을 모드이다.
  • 실제 매개변수 l-value가 있는 표현식이어야 한다.
  • 역방향 할당(Backward assignment) : 실제 매개변수의 l-value가 계산되어 형식 매개변수에 복사된다.
    • 그런 다음 함수가 종료된 후 형식 매개변수의 값이 지정된 위치에 복사된다.
void foo(res int x) {
    x = 5;
}
int y = 2;
foo(y); //y = 5 after this call.
  • 결과 매개변수가 두 개 이상인 경우 역방향 할당은 어떤 순서로 수행되는가?
  • 예) 부작용을 고려하여 왼쪽에서 오른쪽으로.
  • 여러 값을 반환하는 함수의 디자인을 단순화한다.

 


 

Call by Value-Result

  • Call by Value와 Call by Result의 조합
  • 양방향 통신을 구현한다.
  • 실제 매개변수는 l-value를 제공해야 한다.
  • 호출 시 실제 매개변수의 r-vaule가 형식 매개변수에 할당된다.(Call by Value)
    • 복사해서 값으로 주고
  • 그런 다음 형식 매개변수의 값이 실제 매개변수의 l-value을 사용하여 역방향으로 복사된다.(Call by Result)
    • 값을 주소로 받는다.
void foo(val-res int x) {
    x = x + 1;
}
int y = 2;
foo(y); //y = 3 after this call.

 

  • 결과 매개변수가 두 개 이상인 경우
Call by Value-Result Call by Reference
void foo(val-res int x, val-res int y) {
    x = 1;
    y = 3;
    if(x == y)      //x == y → false.
        y = 1;
}

int a = 2;
foo(a, a);         //왼쪽 a는 1, 오른쪽 a는 3 → a is 3.
void foo(ref int x, ref int y) {
    x = 1;
    y = 3;
    if(x == y)       //x == y → true - aliasing.
        y = 1;
}

int a = 2;
foo(a, a);          //a is 1.

 




Call by Name

  • 이 모드는 최신 프로그래밍 언어에서는 더 이상 사용되지 않는다.
  • 함수 본문에 있는 형식 매개변수 이름실제 매개변수 이름으로 바꾸는 방법이다.
void foo(name int x) {
    x = 1;
}
int y = 2;
foo(y); → void foo(int y) { y = 1; }
  • 그러나 교체로 인해 문제가 발생할 수 있다.
int x = 0;
int foo(name int y) {
    int x = 2;
    return x + y;
}
int a = foo(x + 1);
int x = 0;
int foo(name int y) {
    int z = 2;
    return z + y;
}
int a = foo(x + 1);
a = x + x + 1 = 5 a = z + x + 1 = 3
  • 따라서 실제 매개변수와 평가 환경을 전달해야 합니다.

댓글