함수와 매개 변수

gmelan·2022년 4월 30일
0

함수를 호출할 때 같이 넘겨주는 값을 매개 변수(parameter)라 한다. 매개 변수는 함수와 함께 스택 프레임(stack frame)에 저장되는데, 이 때 매개 변수를 스택 프레임에 저장하는 방법이 몇 가지 존재한다.

1. call by value

#include <stdio.h>

void inc(int);

int main(void) {
    int num = 0;

    printf("%d\n", num);
    inc(num);
    printf("%d\n", num);

    return 0;
}

void inc(int value) {
    value++;
    return;
}

/*
결과
0
0
*/

대부분의 프로그래밍 언어에서 기본 옵션으로 채택하고 있는 방법으로, 원본 변수 num의 값을 복사하여 스택 프레임에 저장하는 것이다. 따라서 함수 내부에서 아무리 매개변수 value의 값을 수정해도 그것은 원본이 아닌 사본이기 때문에, 원본 변수 num에는 아무런 영향을 미치지 못한다.

1-1. call by address

#include <stdio.h>

void inc(int*);

int main(void) {
    int num = 0;
    int* p_num = &num; // num을 가리키는 포인터 변수

    printf("(main) num's value: %d\n", num);
    printf("(main) num's address: %p\n", (void*) p_num);
    inc(p_num);
    printf("(main) num's value: %d\n", num);

    return 0;
}

void inc(int* p_value) {
    printf("(inc) p_value's value: %p\n", (void*) p_value);
    printf("(inc) p_value's address: %p\n", &p_value);
    (*p_value)++; // 매개변수 p_value가 가리키는 변수에 1만큼 더함
    return;
}

/*
결과
(main) num's value: 0
(main) num's address: 0x7fffffffddfc
(inc) value's address: 0x7fffffffddfc
(inc) p_value's address: 0x7fffffffddd8
(main) num's value: 1
*/

C와 같이 참조자 개념이 없어 후술할 call by reference를 구현할 수 없는 언어에서 이를 모방할 수 있는 방법으로, 매개 변수로 원본 변수의 주소를 담은 변수, 즉 포인터 변수 p_num을 call by value 형식으로 넘겨주어 그것을 통해 원본 변수를 다룰 수 있게 한다.

2. call by reference

#include <iostream>

using namespace std;

void inc(int& ref_value) {
    cout << "(inc) ref_value's value: " << ref_value << endl;
    cout << "(inc) ref_value's address: " << &ref_value << endl;
    ref_value++;
    return;
}

int main(void) {
    int num = 0;
    int& ref = num; // num을 참조하는 참조자

    cout << "(main) num's value: " << num << endl;
    cout << "(main) num's address: " << &num << endl;
    cout << "(main) ref's value: " << ref << endl;
    cout << "(main) ref's address: " << &ref << endl;
    inc(ref);
    cout << "(main) num's value: " << num << endl;

    return 0;
}
/* 결과
(main) num's value: 0
(main) num's address: 0x7ffcf7a7556c
(main) ref's value: 0
(main) ref's address: 0x7ffcf7a7556c
(inc) ref_value's value: 0
(inc) ref_value's address: 0x7ffcf7a7556c
(main) num's value: 1
*/

C++의 참조자를 사용하면 call by reference를 구현할 수 있다. 주솟값을 전달하여 함수 외부 변수에 접근한다는 점에서는 call by address와 비슷하지만, 참조자 변수 ref의 주솟값이 num의 주솟값과 같다는 것이 주요한 차이점이다. 이는 call by address와 같이 "주솟값을 담은 변수를 전달"한 것이 아닌 "주솟값 그 자체를 전달"한 것이 되고, call by reference의 정의와 상응한다.

python에서의 함수로의 매개 변수 전달 방법

def append_(list_l, value_v):
    list_l.append(value_v)
    return

a = []
print(a)
append_(a, 1)
print(a)

def inc(value):
    value += 1
    return

b = 1
print(b)
inc(b)
print(b)

'''
결과
[]
[1]
1
1
'''

결론부터 말하자면 파이썬에서는 매개 변수가 mutable하다면 call by reference로, immutable하다면 call by value로 전달된다. 이를 passed by assignment라 한다.

0개의 댓글