기본 콘텐츠로 건너뛰기

방송대 방통대 프로그래밍언어론 13강 - 서브프로그램과 인수 전달 방식 - 요약 노트 시험족보 예상문제 - 올에이클래스

0-썸네일-요약노트-프로그래밍언어론-13강

프로그래밍언어론 13강 - 서브프로그램과 인수 전달 방식

서브프로그램의 구조와 호출 과정, 형식인수와 실인수의 대응 방법을 학습한다. 값·결과·값-결과·참조·이름 전달의 데이터 이동과 부작용을 비교하고, 범용 서브프로그램과 분리·독립 컴파일의 차이까지 정리한다.

제1장 서브프로그램의 개념과 구조

1. 프로그램과 서브프로그램

프로그램은 컴퓨터가 실행할 명령어를 나열한 것으로, 실행을 통해 입력을 출력으로 바꾼다. 서브프로그램은 독자적인 입력과 출력을 갖춘 프로그램 조각이다. 서브프로그램의 입력은 인수, 출력은 반환값으로 표현된다. 반복되는 작업을 하나의 단위로 분리하고 필요할 때 호출할 수 있으므로 모듈화 프로그래밍의 기본 기능이 된다.

2. 입구, 출구와 제어흐름

현대적인 서브프로그램은 하나의 입구를 가진다. 호출이 발생하면 호출자의 제어흐름이 호출된 피호출자로 이전된다. 피호출자의 본체를 수행한 뒤 기본 출구에 도달하거나 별도의 return문을 만나면 여러 출구 중 하나로 빠져나와 호출자에게 제어가 복귀한다.

호출 과정: 호출자에서 피호출자로 제어가 이전되고, 피호출자는 인수를 이용해 작업한 뒤 반환값과 제어를 호출자에게 돌려준다.

3. 함수, 프로시저와 서브루틴

함수는 명시적인 반환값이 있는 서브프로그램이고, 프로시저는 명시적인 반환값이 없는 서브프로그램이다. 초기 프로그래밍 언어의 서브루틴은 인수와 반환값의 데이터 흐름이 분명하지 않았으며 입구가 여러 개일 수도 있었다. 현대 서브프로그램은 입구와 데이터 전달을 더 명확히 구조화한다.

분류특징
함수명시적인 반환값이 있음
프로시저명시적인 반환값이 없음
초기 서브루틴데이터 흐름이 불명확하고 여러 입구가 가능했음

4. 정의, 호출, 헤더와 본체

서브프로그램 정의는 서브프로그램이 어떻게 작동하는지 기술한 부분이고, 서브프로그램 호출은 그 서브프로그램의 수행을 요구하는 부분이다. 정의는 헤더와 본체로 나뉜다. 헤더에는 이름, 종류, 매개변수 선언 등이 들어가며 대개 정의의 첫 줄이다. 본체는 호출되었을 때 실행되는 부분으로 보통 헤더를 제외한 정의의 나머지이다.

C의 int sub(int i, int j)는 이름 sub, 반환타입 int, 매개변수 i와 j를 제시하는 헤더이다. 중괄호 안의 return i-j;는 본체이다. sub(x*x, x)는 호출이며 호출 결과가 변수 x에 대입된다.

제2장 프로파일과 인수 대응

1. 매개변수 프로파일과 프로토콜

매개변수 프로파일은 서브프로그램 매개변수의 개수, 순서, 타입을 뜻하며 시그니처(signature)라고도 한다. 같은 이름의 서브프로그램이 여러 개 오버로딩되어 있을 때 호출과 일치하는 정의를 찾는 시그니처 매칭에 사용한다.

서브프로그램 프로토콜은 매개변수 프로파일에 함수의 반환타입을 더한 정보이다. 호출 시 타입 검사를 하는 데 필요하며 정적 타입 언어는 호출 전에 프로토콜이 명시되도록 요구한다. C의 int sub(int, int);는 프로토콜만 제시한 서브프로그램 선언이고, 헤더와 본체를 모두 적은 것은 서브프로그램 정의이다.

구분: 프로파일은 매개변수의 개수·순서·타입이고, 프로토콜은 여기에 함수 반환타입까지 포함한다.

2. 형식인수와 실인수

형식인수 또는 형식매개변수는 서브프로그램 정의에서 외부 정보를 받기 위해 선언한 변수이다. 실인수 또는 실매개변수는 호출할 때 형식인수로 전달하는 실제 값, 식 또는 주소이다. int sub(int i, int j)의 i와 j는 형식인수이고, sub(x*x, x)x*x와 x는 실인수이다.

3. 위치 대응과 키워드 대응

위치에 의한 대응은 실인수를 나열한 순서대로 형식인수와 연결하는 가장 일반적인 방식이며 C, Java, Pascal 등이 사용한다. Python의 sort(n, a)라면 첫 실인수 n은 첫 형식인수 length, 두 번째 a는 list에 대응한다.

키워드에 의한 대응은 형식인수 이름을 명시한다. sort(list=a, length=n)처럼 쓰면 형식인수 순서를 기억하지 않아도 되지만 형식인수의 정확한 이름을 알아야 한다. Ada, Fortran 90, Python 등은 위치와 키워드 방식을 함께 사용할 수 있다.

방식장점주의점
위치 대응짧고 일반적임형식인수 순서를 알아야 함
키워드 대응순서에 구애받지 않고 의미가 분명함형식인수 이름을 알아야 함

4. 기본인수와 가변인수

기본인수는 호출에서 실인수가 생략되었을 때 사용하는 형식인수의 기본값이다. move(Robot r, int x=0, int y=0, int angle=0)에서 move(robo1, 3, 2)는 angle에 기본값 0을 사용한다. Ada, C++, Fortran 90, Python 등이 기본인수를 지원한다.

가변인수 서브프로그램은 받을 수 있는 인수의 개수가 여러 가지인 서브프로그램이다. Java의 sum(int ...ns)sum(1), sum(1,2)처럼 서로 다른 개수의 정수 인수를 받는다. C, Java, Scheme 등에서 가변인수를 사용할 수 있다.

제3장 인수 전달 모델

1. 의미적·개념적·구현 모델

인수 전달은 서로 다른 관점의 세 모델로 설명할 수 있다. 의미적 모델은 프로그래머가 인수를 입력, 출력 또는 입출력 중 어떤 용도로 사용하는지 본다. 개념적 모델은 자료가 값으로 복사되는지, 참조경로가 전달되는지를 도식적으로 본다. 구현 모델은 언어가 실제 전달을 어떤 방식으로 구현하는지 분류한다.

관점분류핵심 질문
의미적 모델입력, 출력, 입출력 모드정보가 어느 방향으로 이동하는가?
개념적 모델값전달, 참조전달값을 복사하는가, 참조경로를 전달하는가?
구현 모델값·결과·값-결과·참조·이름 전달언어 구현에서 전달을 어떻게 실현하는가?

2. 의미적 모델의 데이터 방향

입력모드는 호출자의 실인수에서 피호출자의 형식인수로 정보가 전달되며 현재 대부분 언어의 기본이다. 출력모드는 피호출자가 만든 형식인수 값이 호출자의 실인수로 전달된다. 입출력모드는 호출 시 호출자에서 피호출자로, 복귀 시 피호출자에서 호출자로 양방향 전달이 발생한다.

3. 개념적 모델

개념적 값전달은 실인수의 값을 물리적으로 복사해 전달한다. 개념적 참조전달은 실인수 값을 찾아갈 수 있는 참조경로를 전달한다. 실제 구현 모델에서는 같은 의미를 효율적으로 구현하기 위해 복사 또는 참조경로를 적절히 사용할 수 있다.

제4장 값·결과·값-결과 전달

1. 값전달

값전달(pass-by-value)은 실인수 값을 형식인수에 복사해 입력모드를 구현한다. 대부분의 언어가 채택한다. 첫 번째 구현은 데이터를 실제로 복사하는 방법이다. 단순하지만 큰 배열이나 행렬을 전달하면 복사 비용 때문에 비효율적이다.

두 번째 구현은 참조경로를 전달하되 피호출자가 쓰지 못하게 하는 방법이다. C의 const Matrix *mp처럼 읽기 전용 참조를 사용하면 큰 데이터를 복사하지 않을 수 있지만, 간접참조의 시간 부담이 생긴다. 의미적으로는 값전달의 입력모드를 유지하도록 쓰기를 금지한다.

2. 결과전달

결과전달(pass-by-result)은 피호출자의 형식인수 값을 복귀할 때 호출자의 실인수에 복사해 출력모드를 구현한다. 호출 시 실인수의 초기값을 형식인수 입력으로 사용하는 방식이 아니다.

물리적 복사를 사용하면 여러 결과 형식인수가 같은 실인수에 대응할 때 복사 순서에 따라 최종값이 달라질 수 있다. lor(a,a)에서 left는 3, right는 7이 되었더라도 복귀 시 어느 값을 마지막에 a로 복사하느냐에 따라 결과가 달라진다.

참조경로를 전달해 구현할 수도 있지만 실인수의 초기값 사용을 금지해 출력모드 의미를 지킨다. 이때 실인수 주소를 언제 결정하는지가 중요하다. 대부분 호출 시점에 주소를 정한다. lor(idx, list[idx])라면 두 번째 실인수의 주소는 호출 당시 idx 값으로 결정되며, 피호출자의 작업으로 idx가 바뀌어도 이미 정한 복사 대상 주소는 바뀌지 않는다.

3. 값-결과전달

값-결과전달(pass-by-value-result)은 호출할 때 실인수 값을 형식인수로 복사하고, 복귀할 때 형식인수 값을 실인수로 다시 복사해 입출력모드를 구현한다. 두 방향 모두 물리적 복사를 사용하므로 복사에 의한 전달(pass-by-copy)이라고도 한다.

형식인수는 독립된 복사본이므로 수행 중 같은 대상을 공유하는 별칭 문제가 발생하지 않는 것이 장점이다. 그러나 입·출력 양쪽에서 복사하므로 비효율적이고, 값전달의 복사 비용과 결과전달의 복귀 복사 순서 및 주소 결정 문제를 모두 포함할 수 있다.

방향 정리: 값전달은 호출 시 안으로, 결과전달은 복귀 시 밖으로, 값-결과전달은 호출과 복귀 두 시점에 모두 복사한다.

제5장 참조전달과 별칭

1. 참조전달

참조전달(pass-by-reference)은 실인수의 주소 또는 참조를 형식인수에 전달한다. 형식인수와 실인수가 같은 변수를 가리키므로 피호출자의 수정이 즉시 호출자 변수에 반영되어 입출력모드를 구현한다. 복사 대신 경로만 전달하므로 전달 과정 자체는 효율적이며 공유에 의한 전달(pass-by-sharing)이라고도 한다.

2. 별칭 문제

별칭(alias) 문제는 하나의 대상을 서로 다른 이름으로 지칭할 때 발생한다. 동일한 변수를 두 참조 매개변수에 전달하는 실인수 충돌, 같은 배열 원소를 두 번 전달하는 배열원소 충돌, 서브프로그램이 사용하는 전역변수를 다시 실인수로 전달하는 형식인수와 전역변수 충돌이 대표적이다.

sqSum(a,a)에서 두 형식인수 x1과 x2는 모두 같은 a를 가리킨다. a가 2일 때 x1을 제곱하면 같은 대상이 4가 되고, 이어 x2를 제곱하면 이미 바뀐 4가 다시 제곱되어 16이 된다. 반환식도 같은 대상을 두 번 읽는다. 독립된 두 값을 전달했다고 생각한 경우와 다른 결과가 나오므로 참조 별칭을 주의해야 한다.

참조전달의 양면성: 복사 비용은 작지만 피호출자 안의 변경이 즉시 공유 변수에 반영되므로 인수끼리 같은 대상을 가리키는지까지 분석해야 한다.

제6장 이름전달과 전달 방식 비교

1. 이름전달

이름전달(pass-by-name)은 실인수의 이름, 더 정확히는 실인수 식을 형식인수 대신 사용할 수 있도록 전달하는 방식이다. 형식인수가 사용될 때마다 호출 문맥의 실인수 식이 사용된다. 값의 복사나 고정된 참조경로만 전달하는 방식과 달라 특정 의미적·개념적 모델 하나에 직접 대응하지 않는다.

double(a[i])에서 본체가 x := 2*x라면 이름 x가 쓰일 때마다 a[i]가 대입된다. 호출 중 i가 바뀌면 이후 a[i]가 나타내는 원소도 달라질 수 있다. 이런 늦은 바인딩은 유연하지만 실행 흐름을 이해하기 어렵게 한다.

2. 이름전달의 장단점

이름전달은 늦은 바인딩 덕분에 젠슨의 기법(Jensen's Device)과 같은 범용 서브프로그램을 만들 수 있다. 반면 형식인수를 참조할 때마다 실인수 식을 다시 해석해야 해 매우 비효율적이고, 인수 전달의 의미가 난해하다.

swap(i, x[i]) 같은 호출은 특히 주의해야 한다. 이름전달에서는 첫 대입으로 i가 바뀌면 그 뒤의 x[i]가 다른 배열 원소를 가리킬 수 있다. 따라서 일반적인 참조전달의 고정 주소 교환과 결과가 달라질 수 있다.

3. 참조전달과 이름전달 비교

list={1,2,3}, i=1에서 swap(i,list[i])를 생각하자. 참조전달은 호출 시 i와 당시의 list[1] 주소를 고정한다. 교환 후 i는 2이고 list는 {1,1,3}이 된다. 이름전달은 형식인수가 쓰일 때마다 list[i]를 다시 해석한다. i가 2로 바뀐 뒤의 접근은 list[2]를 가리켜 최종 list가 {1,2,1}이 된다.

4. 참조전달과 값-결과전달 비교

전역 i=1, list={1,2,3}에서 fun(i,list[i])를 호출하고 본체가 i=b를 수행한다고 하자. 참조전달에서는 b가 호출 당시 list[1]을 가리키므로 전역 i는 즉시 2가 된다. 값-결과전달에서는 형식인수 a와 b가 복사본이고 본체가 이 형식인수를 변경하지 않으므로 복귀할 때 원래 복사값 1과 2가 각 실인수에 되돌아가며 i는 1, 배열은 그대로이다.

방식전달 핵심대표 문제 또는 비용
실인수 값을 호출 시 복사큰 데이터 복사 비용
결과형식인수 값을 복귀 시 복사복사 순서와 대상 주소 결정
값-결과호출·복귀 시 두 번 복사복사 비용과 결과전달 문제
참조실인수 참조경로를 고정해 공유별칭 문제
이름사용 시마다 실인수 식을 적용비효율과 난해한 늦은 바인딩

제7장 범용 서브프로그램과 컴파일

1. 범용 서브프로그램

범용 서브프로그램은 여러 용도로 사용할 수 있는 서브프로그램이다. 여러 타입의 인수에 적용하는 다형 서브프로그램과 다양한 목적에 적용하는 다목적 서브프로그램으로 나뉜다.

2. 다형 서브프로그램

다형 서브프로그램은 여러 타입의 인수에 적용할 수 있으며 제너릭(generic) 서브프로그램이라고도 한다. C는 매크로 확장과 void * 타입을 이용할 수 있지만 인수 타입 검사가 어렵다. C++는 템플릿, Java는 제너릭을 이용한다. 타입을 인수로 받아 여러 타입을 다루는 성질을 매개변수적 다형성이라고 한다.

3. 다목적 서브프로그램과 젠슨의 기법

다목적 서브프로그램은 타입뿐 아니라 다양한 계산 목적에 적용된다. Algol 60의 젠슨의 기법은 이름전달의 늦은 바인딩을 이용한다. 합계 서브프로그램에 반복 변수 i, 하한 lo, 상한 hi와 계산할 식 term을 전달하면, 반복 중 i가 변할 때마다 term이 새 i로 평가된다. 따라서 i*i를 전달하면 1부터 10까지 제곱의 합을 계산하는 등 하나의 sum을 여러 합계 계산에 쓸 수 있다.

4. 분리컴파일과 독립컴파일

여러 프로그래머가 각 모듈을 작성하려면 자신의 소스 코드를 따로 컴파일할 수 있어야 한다. 분리컴파일은 코드 사이의 인터페이스 정보를 이용해 프로그램 일부를 다른 부분과 분리하여 컴파일한다. Ada, Fortran 90, Modula-2 등이 해당한다.

독립컴파일은 인터페이스 정보 없이 프로그램 일부를 다른 부분과 분리해 컴파일한다. Fortran II부터 77, C, C++ 등이 해당한다. 둘 다 부분별 컴파일이지만, 다른 모듈과 주고받는 인터페이스 정보를 컴파일 과정에서 사용하는지가 핵심 차이이다.

구분: 분리컴파일은 인터페이스 정보를 사용하고, 독립컴파일은 인터페이스 정보 없이 각 부분을 컴파일한다.

핵심 개념 정리

서브프로그램은 독자적인 입력과 출력을 갖춘 프로그램 조각이다. 명시적 반환값이 있으면 함수, 없으면 프로시저이다. 헤더에는 이름·종류·매개변수 선언이, 본체에는 호출 시 실행할 내용이 들어간다. 매개변수 프로파일은 개수·순서·타입이며, 프로토콜은 여기에 반환타입까지 포함한다. 정의의 변수는 형식인수, 호출에서 전달하는 값·식·주소는 실인수이다.

값전달은 호출 시 안으로, 결과전달은 복귀 시 밖으로, 값-결과전달은 양방향으로 값을 복사한다. 참조전달은 실인수의 참조경로를 공유해 효율적이지만 별칭 문제가 생길 수 있다. 이름전달은 형식인수를 사용할 때마다 실인수 식을 적용해 유연하지만 비효율적이고 의미가 어렵다.

범용 서브프로그램은 여러 타입에 적용되는 다형 서브프로그램과 여러 목적에 적용되는 다목적 서브프로그램으로 나뉜다. C++ 템플릿과 Java 제너릭은 매개변수적 다형성을 지원하고, 젠슨의 기법은 이름전달의 늦은 바인딩을 활용한다. 분리컴파일은 인터페이스 정보를 이용하지만 독립컴파일은 이를 사용하지 않는다.

최종 정리: 인수 전달 문제는 값이 어느 시점에 어느 방향으로 이동하는지, 실인수 주소가 고정되는지, 여러 이름이 같은 대상을 공유하는지를 차례로 확인해야 한다. 복사는 독립성을 주지만 비용이 들고, 참조는 효율적이지만 별칭을 만들며, 이름전달은 식을 늦게 결합해 가장 유연한 대신 가장 이해하기 어렵다.

예상문제 20선

1. 서브프로그램의 입력과 출력에 해당하는 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
서브프로그램은 인수를 입력으로 받아 작업하고 반환값을 출력으로 제공한다.

2. 함수와 프로시저의 구분 기준은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
명시적인 반환값이 있으면 함수이고 없으면 프로시저이다.

3. 서브프로그램 프로토콜에 포함되는 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
프로파일은 매개변수 개수·순서·타입이며 프로토콜은 이에 반환타입을 더한다.

4. int sub(int i,int j)sub(x*x,x)에서 형식인수와 실인수를 옳게 연결한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
형식인수는 정의에서 정보를 받을 변수이고 실인수는 호출에서 전달하는 실제 식이나 값이다.

5. 키워드에 의한 인수 대응의 장점은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
형식인수 이름을 직접 지정하므로 순서에 구애받지 않지만 이름은 정확히 알아야 한다.

6. 가변인수 서브프로그램의 특징은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
가변인수 서브프로그램은 sum(1), sum(1,2)처럼 서로 다른 개수의 인수를 받을 수 있다.

7. 입력·출력·입출력 모드로 인수 용도를 분류하는 모델은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
의미적 모델은 프로그래머가 인수를 어느 방향의 정보 전달에 사용하는지 본다.

8. 값전달(pass-by-value)의 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
값전달은 호출자의 값을 피호출자용 형식인수 복사본으로 전달한다.

9. 큰 행렬을 물리적으로 복사하는 값전달의 주된 단점은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
데이터가 클수록 물리적 복사에 시간과 공간이 많이 든다.

10. 결과전달(pass-by-result)이 구현하는 의미적 모드는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
결과전달은 피호출자가 만든 형식인수 값을 복귀 시 실인수로 내보낸다.

11. 결과전달에서 lor(a,a)처럼 같은 실인수를 두 번 전달할 때 생길 수 있는 문제는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
서로 다른 결과 형식인수 값이 같은 실인수에 복사되면 마지막 복사가 최종값을 결정한다.

12. 값-결과전달의 처리 순서는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
값-결과전달은 입출력 두 방향에서 복사하므로 복사에 의한 전달이라고도 한다.

13. 값-결과전달의 장점은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
복사된 형식인수끼리는 같은 실인수 저장공간을 수행 중 직접 공유하지 않는다.

14. 참조전달의 특징으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
참조전달은 공유에 의한 전달로 효율적이지만 여러 이름이 같은 대상을 가리키는 별칭 문제가 생길 수 있다.

15. 참조전달에서 별칭 문제가 발생하는 사례는?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
x1과 x2가 같은 a를 가리키므로 한 형식인수의 변경이 다른 형식인수로 읽는 값도 즉시 바꾼다.

16. 이름전달(pass-by-name)에 대한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
이름전달은 늦은 바인딩으로 유연하지만 참조 때마다 실인수 식을 처리해 비효율적이고 이해하기 어렵다.

17. i=1, list={1,2,3}에서 swap(i,list[i])를 참조전달로 수행한 뒤의 값은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ②
참조전달은 호출 시 i와 당시 list[1]의 주소를 고정해 두 대상을 교환한다.

18. 젠슨의 기법이 이용하는 핵심 성질은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ④
반복 변수가 변할 때마다 전달한 term 식이 새 값으로 평가되어 하나의 합계 서브프로그램을 여러 계산에 쓸 수 있다.

19. 다형 서브프로그램에 대한 설명으로 옳은 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ③
타입을 인수화해 여러 타입을 다루는 성질을 매개변수적 다형성이라고 한다.

20. 분리컴파일과 독립컴파일의 차이를 옳게 설명한 것은?

정답입니다.

오답입니다. 답안을 다시 선택해 보세요.

정답 및 해설 보기

정답: ①
둘 다 부분별 컴파일 방식이지만 모듈 사이의 인터페이스 정보를 사용하는지가 다르다.

댓글