8번째_서브프로그램

  • by

한성대학 김성동 교수의 프로그래밍 언어론을 배우는 글입니다.

서브 프로그램

서브 프로그램의 기초

  • 서브 프로그램을 사용하는 이유
    • 프로그램의 크기를 줄이기 위해 나누어 씁니다.

      ▶ 모듈화 프로그래밍 원리를 준수.
    • 가독성 가독성 향상.
    • 유지 보수 및 디버깅 용이성.
  • 서브 프로그램의 다른 이름
    • Function(함수)
    • Procedure(프로시저)
    • Subroutine (서브 루틴)
  • 서브 프로그램 요소
    • 이름
    • 파라미터(인수) 리스트(parameter/argument list)
    • 바디(body)
    • 참조 환경


서브 프로그램 요소 이미지 1

  • 서브 프로그램 호출(call)
    • 이름.
    • 매개변수의 수와 유형.
    • 반환 값의 수와 유형.
    • 서브 프로그램에서 실행되는 기능.
      : what not how (어떻게 하는지 알아야 함) → 알고리즘 추상화(abstraction)
    • 호출 방법의 예: C 언어 → proc(i, j);
      결과를 반환하는 방법: C 언어 → return.


서브 프로그램 호출(call) 이미지 1

  • 재귀 함수
    • 함수 자체를 이용하여 function을 구현.
    • 이해하기 쉽고 간결하게 작성하십시오.


재귀 함수 이미지

  • 블록 구조(block structure)
    • Algol(알골)이라는 언어로 제시.
    • 한 프로그램은 여러 블록을 모아서 만들 수 있습니다.

    • 블록 = 선언부(declaration part) + 실행부(execution part)
    • C 언어로 차단
      – 이름이 없는 블록 = if문이나 for문 등에 사용하는 블록
      – 명명된 블록 = 함수
      – 명명된 중첩 블록 없음(pascal에서는 가능)
    • 블록 구조를 이용한 정적 영역 규칙(static scope rule)을 활용한다 → 컴파일을 한다
  • 특징
    • 로컬 변수(local varible) 선언
      – 블록 외부에서 액세스할 수 없음
      정보 은폐
    • 블록 실행이 시작되면 로컬 변수의 메모리가 할당됩니다(스택 동적 변수/메모리).
      → 블록 종료시 메모리 반환
    • 이름이 있는 블록만 호출 가능
      – 블록 내의 서브 프로그램은 블록 외부에서 호출할 수 없습니다.


      내부 블록은 외부 블록에서 숨겨져 있습니다.

유형 인수/실제

  • 실제 인자(actual parameter)
    • 서브 프로그램에 전달되는 실제 값을 가진 매개 변수
    • 호출 문에서 사용되는 변수
    • result := gcd( a,b );
  • 형식 인수
    • 함수 선언에 표시되는 매개변수
    • 함수 정의를 할 때 이러한 파라미터를 받아야한다고 폼(형식)을 정해 둔 것
      실제 값을 모른다 실연자받지 않으면 모른다.

    • function gcd( m, n :integer):integer.
  • 타입 파라미터와 실제 파라미터의 대응
    • 위치별 대응 ex.C 언어
    • 이름별 대응 ex.Python
    • 매개 변수의 기본값(default value)
      – ex. C++, Ada (C에는 없음)
      – 실제 파라미터의 수가 타입 파라미터의 수보다 쓸 수 있다.


(위치에 의한 대응) C언어에서의 실/형식 파라미터간의 대응

(이름으로 대응) ex.Python – ai Dense 신경망

파라미터 전달 방법

1. 값별 호출(값 전달) – call by value

  • 이 값으로 함수에 작업하도록 부릅니다.

  • 실제 매개변수 값(r-value)을 유형 매개변수에 전달
  • 실제 파라미터와 타입 파라미터는 다른 메모리 공간점유하다
    포맷 파라미터는 해당 블록이 끝나면 메모리 공간에서 사라집니다.



파란색 블록(형식 인수)은 연산이 끝나고 메모리에서의 히트(a, b는 big에 값을 주고 add 블록이 끝나면 사라집니다)

2. 참조를 통한 호출(참조 전송) – call by reference

  • 실제 파라미터의 주소(l-value)를 타입 파라미터에 전달합니다.

  • 실제 파라미터와 타입 파라미터는 서로 같은 메모리 공간점유하다
  • 형식 매개 변수를 조작하면 실제 매개 변수가 가리키는 값을 조작하는 것과 같습니다.

    따라서 호출된 함수가 종료되더라도 작업된 값은 그대로 유지됩니다.




main에서는 i는 4, big는 62가 출력된다

3. 이름에 의한 호출(이름 전달) – call by name

  • 매개변수를 사용할 때마다 필요한 실제 매개변수의 l-value 또는 r-value가 계산되고 사용됩니다.


파란색 상자를 오른쪽 상자처럼 수정하면 call by name

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의 예.

  • 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 언어 배열(참조 변수)의 예

  • C 언어의 배열 (참조 변수)의 예를 살펴 보겠습니다.

    • the sum = 14, b(0) = 20, b(1) = 4; b(2)=8 을 출력한다.

2. 레코드 전송(struct in C)

  • 참조 배달을 많이 사용.

3. sub-program passing


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와 CEP를 activation record에 저장
      – 새로운 서브 프로그램을 위해 CIP 및 CEP 수정
    • 반환
      – Pop old IP와 EP → CIP와 CEP를 복구하여 원래 호출한 프로그램을 차례로 실행
  • activation record 단순화
    • IP와 EP가 가거나 오지 않고 한 번에 끝납니다.

    • AR : 호출시 생성, 종료시 파괴 → 실행시간 증가
    • 생성 파괴 대신 서브 프로그램을 복사하여 붙여넣기 → 실행 시간 단축
    • AR을 초기화합니다.

    • CEP는 필요하지 않으며 CIP만 필요합니다.

    • FORTRAN, COBOL… 등.

  • 재귀 호출 구현
    • 자신을 불러
    • 특징
      • 첫 번째 AR이 있으면 두 번째 AR이 생성됩니다.

      • 각 AR은 서로 독립적입니다.

      • AR의 단순화 모델이 성립하지 않는다.

    • stack 기반의 AR 관리를 하게 된다
    • 레코드 체인(record chain)
      • 스택 순서에 따라 AR 연결
      • 다이나믹 체인. 실행 순서를 나타내는 체인. 저장된 환경 포인터 저장된 것을 연결한 것.