한성대학 김성동 교수의 프로그래밍 언어론을 배우는 글입니다.
서브 프로그램
서브 프로그램의 기초
- 서브 프로그램을 사용하는 이유
- 프로그램의 크기를 줄이기 위해 나누어 씁니다.
▶ 모듈화 프로그래밍 원리를 준수. - 가독성 가독성 향상.
- 유지 보수 및 디버깅 용이성.
- 프로그램의 크기를 줄이기 위해 나누어 씁니다.
- 서브 프로그램의 다른 이름
- Function(함수)
- Procedure(프로시저)
- Subroutine (서브 루틴)
- 서브 프로그램 요소
- 이름
- 파라미터(인수) 리스트(parameter/argument list)
- 바디(body)
- 참조 환경
- 서브 프로그램 호출(call)
- 이름.
- 매개변수의 수와 유형.
- 반환 값의 수와 유형.
- 서브 프로그램에서 실행되는 기능.
: what not how (어떻게 하는지 알아야 함) → 알고리즘 추상화(abstraction) - 호출 방법의 예: C 언어 → proc(i, j);
결과를 반환하는 방법: C 언어 → return.
- 재귀 함수
- 함수 자체를 이용하여 function을 구현.
- 이해하기 쉽고 간결하게 작성하십시오.
- 블록 구조(block structure)
- Algol(알골)이라는 언어로 제시.
- 한 프로그램은 여러 블록을 모아서 만들 수 있습니다.
- 블록 = 선언부(declaration part) + 실행부(execution part)
- C 언어로 차단
– 이름이 없는 블록 = if문이나 for문 등에 사용하는 블록
– 명명된 블록 = 함수
– 명명된 중첩 블록 없음(pascal에서는 가능) - 블록 구조를 이용한 정적 영역 규칙(static scope rule)을 활용한다 → 컴파일을 한다
- 특징
- 로컬 변수(local varible) 선언
– 블록 외부에서 액세스할 수 없음
– 정보 은폐 - 블록 실행이 시작되면 로컬 변수의 메모리가 할당됩니다(스택 동적 변수/메모리).
→ 블록 종료시 메모리 반환 - 이름이 있는 블록만 호출 가능
– 블록 내의 서브 프로그램은 블록 외부에서 호출할 수 없습니다.
→ 내부 블록은 외부 블록에서 숨겨져 있습니다.
- 로컬 변수(local varible) 선언
유형 인수/실제
- 실제 인자(actual parameter)
- 서브 프로그램에 전달되는 실제 값을 가진 매개 변수
- 호출 문에서 사용되는 변수
- result := gcd( a,b );
- 형식 인수
- 함수 선언에 표시되는 매개변수
- 함수 정의를 할 때 이러한 파라미터를 받아야한다고 폼(형식)을 정해 둔 것
실제 값을 모른다 실연자받지 않으면 모른다. - function gcd( m, n :integer):integer.
- 타입 파라미터와 실제 파라미터의 대응
- 위치별 대응 ex.C 언어
- 이름별 대응 ex.Python
- 매개 변수의 기본값(default value)
– ex. C++, Ada (C에는 없음)
– 실제 파라미터의 수가 타입 파라미터의 수보다 쓸 수 있다.
파라미터 전달 방법
1. 값별 호출(값 전달) – call by value
- 이 값으로 함수에 작업하도록 부릅니다.
- 실제 매개변수 값(r-value)을 유형 매개변수에 전달
- 실제 파라미터와 타입 파라미터는 다른 메모리 공간점유하다
포맷 파라미터는 해당 블록이 끝나면 메모리 공간에서 사라집니다.
2. 참조를 통한 호출(참조 전송) – call by reference
- 실제 파라미터의 주소(l-value)를 타입 파라미터에 전달합니다.
- 실제 파라미터와 타입 파라미터는 서로 같은 메모리 공간점유하다
- 형식 매개 변수를 조작하면 실제 매개 변수가 가리키는 값을 조작하는 것과 같습니다.
따라서 호출된 함수가 종료되더라도 작업된 값은 그대로 유지됩니다.
3. 이름에 의한 호출(이름 전달) – call by name
- 매개변수를 사용할 때마다 필요한 실제 매개변수의 l-value 또는 r-value가 계산되고 사용됩니다.
4. Java에서 매개 변수 전달
- 값 전달(call by value)
: integer, real, character, boolean - 참조 전송(call by reference)
: String, array, object variable
5. 형식 파라미터 지정
- 함수의 원형 표시 (function prototyping)
: 함수에 대한 정보를 컴파일에 전달합니다(함수 원형 작성). - 컴파일러에 정보 제공 → error checking
- 함수의 원형 (function prototype)
- 서브 프로그램 이름
- 매개변수 유형 – 정수 또는 실수…
- 반환값의 형태(type of return values) – 주소인가 값인가.
- java 예제 설명
- 값 전달 및 참조 전달의 경우.
- 클래스 M의 주요 함수를 살펴 보겠습니다.
– 정수 a와 배열 b가 선언되었습니다.
a는 속성 변수(call by value), b는 참조 변수(call by reference).
– change라는 메소드를 호출하는 P클래스를 p1로 오브젝트 생성했다.
– a를 4로 변경해 change 메소드에 대입했지만, 속성 변수와 값이 바뀌었다.
– b는 참조 변수이므로 b가 가리키는 0번 인덱스의 값을 변경하므로 값이 바뀝니다.
– System.out.println에서 a는 4, b(0)은 12, b(1)은 2를 출력합니다.
복잡한 데이터 전달 방법
- 복합 데이터를 전달합니다.
기본적으로 call by reference 를 사용합니다.
1. 배열 전송
- 값 전달: copy cost
- 참조 전달 : 변경된 값을 반환하는 데 적합합니다.
- 배열의 이름을 전달하면 주소가 전달됩니다.
(C 언어에서)
- C 언어의 배열 (참조 변수)의 예를 살펴 보겠습니다.
- the sum = 14, b(0) = 20, b(1) = 4; b(2)=8 을 출력한다.
- the sum = 14, b(0) = 20, b(1) = 4; b(2)=8 을 출력한다.
2. 레코드 전송(struct in C)
- 참조 배달을 많이 사용.
3. sub-program passing
4. 함수 중복(function overloading)
- 같은 함수 이름이지만 다른 매개 변수를 가질 때.
- C 언어로는 안되지만, C 플러스 언어나 Java 등으로 가능
서브 프로그램 실행 방법
* 상태 저장 → 서브 프로그램에서 제어를 반환 → 호출 다음 문에서 실행
- 서브 프로그램 호출
- 현재 실행중인 프로그램의 상태 저장
- 서브 프로그램에서 제어를 반환합니다.
- 호출하여 문장 실행
- 서브프로그램은 유형 후에만 제어를 리턴할 수 있으며, 재시작 시 첫 번째 행에서 재개됩니다.
1) Co-routine
- 서브 프로그램과 유사
- 서브 프로그램 종료 전에 제어를 반환할 수 있는
- 다시 호출하면 제어가 반환된 위치에서 수행 재개(resume)
- 호출하는 서브 프로그램과 호출되는 서브 프로그램은 동등한 관계(independent relation)
2) 서브루틴
- 서브프로그램이 종료된 후 제어를 리턴
- 실행 단계
①메인 프로그램에서 시작
② 다른 서브 프로그램의 호출. 서브프로그램은 다른 서브프로그램을 호출할 수 있습니다.
③ 호출한 서브프로그램(caller)은 저장되어 실행을 정지하고, 호출된 서브프로그램(callee)이 실행을 개시
④ 호출된 서브 프로그램이 종료후에 제어를 돌려준다
⑤ 호출한 문장의 다음 문장으로 실행을 재개
- 어셈블리 언어(assembly language)
- 저급 언어에 해당(기계어)
- 복사 규칙(copy rule) : 호출문(call statement)
호출된 서브 프로그램의 모든 문장을 저장하고 주로 복사하는 형식
서브 프로그램 구현 방법
* 서브 프로그램 실행 프로세스를 올바르게 진행하려면 CIP 및 CEP 정보를 유지해야 합니다.
- 구현
- 고려사항
– sub-program = 정의(definition, 코드 작성) / 활성화(activation, 메모리에 올라 동작)
– Activation = code segment(코드 부분) + activation record(=ar, 액티브 레코드) - code
- 실행 코드, 상수
- 실행 중에는 변경되지 않습니다.
- 메모리에 정적으로 저장됩니다 (프로그램 시작부터 끝까지 계속)
- 활성화 레코드(=AR)
- 프로그램 실행 환경 정보 : 로컬 변수, 파라미터 (데이터 부분)
- 서브 프로그램이 호출될 때 작성(할당)됩니다.
- 서브 프로그램 종료시에 파괴(해제)된다.
- 고려사항
- 올바르게 서브 프로그램을 실행하려면 두 부분을 알아야합니다.
- CIP (current instruction pointer) 현재 명령 포인터 = PC(program counter)
메모리의 어디에 있는 코드인지를 나타내는 정보. - CEP (current environment pointer) 현재 환경 포인터
메모리의 데이터가 어디에 있는지, 어떤 주소에 데이터가 있는지를 나타내는 정보.
- CIP (current instruction pointer) 현재 명령 포인터 = PC(program counter)
- 단순 호출/반환 구조 구현
- 전화
– CIP와 CEP를 activation record에 저장
– 새로운 서브 프로그램을 위해 CIP 및 CEP 수정 - 반환
– Pop old IP와 EP → CIP와 CEP를 복구하여 원래 호출한 프로그램을 차례로 실행
- 전화
- activation record 단순화
- IP와 EP가 가거나 오지 않고 한 번에 끝납니다.
- AR : 호출시 생성, 종료시 파괴 → 실행시간 증가
- 생성 파괴 대신 서브 프로그램을 복사하여 붙여넣기 → 실행 시간 단축
- AR을 초기화합니다.
- CEP는 필요하지 않으며 CIP만 필요합니다.
- FORTRAN, COBOL… 등.
- IP와 EP가 가거나 오지 않고 한 번에 끝납니다.
- 재귀 호출 구현
- 자신을 불러
- 특징
- 첫 번째 AR이 있으면 두 번째 AR이 생성됩니다.
- 각 AR은 서로 독립적입니다.
- AR의 단순화 모델이 성립하지 않는다.
- 첫 번째 AR이 있으면 두 번째 AR이 생성됩니다.
- stack 기반의 AR 관리를 하게 된다
- 레코드 체인(record chain)
- 스택 순서에 따라 AR 연결
- 다이나믹 체인. 실행 순서를 나타내는 체인. 저장된 환경 포인터 저장된 것을 연결한 것.