매개변수 전달(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 |
- 따라서 실제 매개변수와 평가 환경을 전달해야 합니다.
'프로그래밍언어론' 카테고리의 다른 글
[프로그래밍언어론] 27. 자료형(Data Types) (1) | 2023.10.17 |
---|---|
[프로그래밍언어론] 26. 바인딩 정책(Binding Policy) (1) | 2023.10.17 |
[프로그래밍언어론] 24. 컨트롤 추상화(Control Abstraction) (0) | 2023.10.17 |
[프로그래밍언어론] 23. 파이썬 피보나치 수열 재귀 (0) | 2023.10.12 |
[프로그래밍언어론] 22. 재귀(Recursion) (0) | 2023.10.12 |