📌 개요
🔑 학습 키워드
┗ 서브프로그램 개념: 프로그램, 서브프로그램(인수 ,반환값, 제어흐름 => 호출자, 피호출자)
┗ 서브프로그램 분류(종류): 함수, 프로시저, 서브루틴
┗ 서브프로그램 관련 용어: 정의, 헤더, 본체, 호출, 매개변수 프로파일, 프로토콜, 형식/실 인수
┗ 인수 전달 모델: 의미적 모델, 개념적 모델, 구현 모델
┗ 구현 모델: 값 전달, 결과 전달, 값-결과 전달, 참조 전달, 이름 전달
┗ 범용 서브프로그램: 다형 서브프로그램, 다목적 서브프로그램
┗ 분리 컴파일, 독립 컴파일
💡 1. 서브프로그램 개념
[ 서브프로그램 이란? ]
┗ 프로그램:
- 컴퓨터가 실행할 명령어를 나열한 것
- 프로그램 실행을 통해 입력을 출력으로 바꿈
┗ 서브프로그램:
- 독자적인 입력과 출력을 갖춘 프로그램 조각
-> 서브프로그램의 입력: '인수'
-> 서브프로그램의 출력: '반환값'
┗ 서브프로그램의 특징:
- '하나의 입구': 서브프로그램으로 들어가는 입구는 하나
- '여러 출구': 서브프로그램에서 나가는 출구는 여러 곳 가능
- '기본 출구와 반환': 서브프로그램의 맨 끝은 자동적으로 출구가 됨
-> '반환': 별도의 return문을 통해 출구 지정 가능
- '제어 흐름 이전':
-> (1) 서브프로그램을 호출하면 호출자의 수행은 멈춤
-> (2) 이후, 제어 흐름은 피호출자로 넘어가서 피호출자의 입구부터 수행됨
-> '호출자': 서브프로그램을 호출한 프로그램
-> '피호출자': 호출된 서브프로그램
- '제어 흐름 복귀': 피호출자가 출구를 만나 종료되면 제어 흐름은 호출자로 넘어가서 호출자의 수행이 재개됨
[ 서브프로그램 분류 ]
┗ 함수: 명시적 반환값이 있는 서브프로그램
┗ 프로시저: 명시적 반환값이 없는 서브프로그램
┗ 서브루틴: 프로그래밍 언어 초기의 서브프로그램
- 인수 전달, 반환값 전달 등의 데이터 흐름이 명확하지 않음
- 입구가 여러 개일 수 있음
[ 서브프로그램 관련 용어 ]
서브프로그램
│
├── 서브프로그램 정의
│ │
│ ├── 헤더
│ │
│ └── 본체
│
└── 서브프로그램 호출
┗ 서브프로그램 정의: 서브프로그램의 작동을 기술한 부분
┗ 서브프로그램 호출: 서브프로그램이 수행될 것을 요구하는 부분
┗ 서브프로그램 헤더: 서브프로그램의 이름, 종류, 매개변수 선언 등을 포함하는 부분
┗ 서브프로그램 본체: 서브프로그램이 호출되었을 때 실행되는 부분
┗ 매개변수 프로파일: 서브프로그램의 "매개변수"의 "개수", "순서", "타입"을 의미
- 매개변수 프로파일 => "시그니처"라고도 함
- 이름이 같은 서브프로그램이 여러 개 오버로딩된 경우
-> 서브프로그램 호출과 일치하는 서브프로그램을 찾는 데 사용이 되기도 함
┗ 서브프로그램 프로토콜: 매개변수 프로파일 + 반환 타입(함수의 경우)
- 서브프로그램 호출 시 타입 검사를 위해 필요
- 정적 타입 언어는 서브프로그램 호출 전에 서브프로그램 프로토콜이 명시될 것을 규정
- 서브프로그램 선언
-> 쉽게말해, "이 서브프로그램을 호출하려면 어떤 형태로 값을 주고받아야 하는가?"를 정해 놓은 약속
┗ 서브프로그램 선언과 정의의 차이:
- "서브프로그램 선언": 서브프로그램 프로토콜만 명시
- "서브프로그램 정의": 서브프로그램 헤더와 본체 모두 명시
┗ 형식인수와 실인수:
- "형식인수(형식매개변수)": 서브프로그램 정의에서 외부로부터 전달된 정보를 받기 위해 선언한 변수
- "실인수(실매개변수)": 서브프로그램 호출 시 형식인수로 전달될 실제 값이나 주소
-> 서브프로그램 호출 시, 호출자의 실인수가 피호출자의 형식인수로 전달되는 구조임
┗ 실인수와 형식인수의 대응:
- "위치에 의한 대응"
-> 가장 일반적 => 매개변수 위치에 따라 타입 등을 보고 대응하는 것임.
-> C, Java, Pascal 등
- "키워드에 의한 대응"
-> 형식인수 이름에 의한 대응 방법 => 실인수에서 키워드를 지정
-> SORT(LIST => A, LENGTH => N);
-> '장점': 형식인수 순서를 기억하지 않아도 됨
-> '단점': 형식인수 이름을 기억해야 함
- "위치 및 키워드에 의한 대응 병용"
-> Ada, Fortran, Python 등 => 둘 다 사용 가능
┗ 인수전달 고려 사항:
- "기본 인수"
-> 실인수가 주어지지 않을 경우 사용하는 값
-> 형식인수의 기본값
-> Ada, C++, Fortran 90, Python 등
-> 예시: C++
=> void move(Robot r, int x = 0, int y = 0, int angle = 0)
- "가변인수 서브프로그램"
- 받을 수 있는 인수 개수가 여러 가지가 될 수 있는 서브프로그램
- C, Java, Scheme 등
-> 예시: int sum(int num, ...) {}
💡 2. 매개변수와 인수 전달
[ 인수 전달 모델 ]
- 서브프로그램을 호출할 때, 호출하는 쪽의 실인수 값(인수)을
-> 호출되는 서브프로그램의 매개변수에게 어떻게 전달할 것인가를 설명하는 모델을 의미
예: "값을 복사해서 전달할까?", "주소를 전달할까?", "변수를 직접 전달할까?" 등을 정할 수 있음.
┗ 의미적 모델: 프로그래머가 "어떤 용도"로 "인수"를 사용하느냐 하는 관점에서 바라본 모델
- (1) '입력 모드': 호출자의 실인수가 피호출자의 형식인수로 전달
-> 현재 대부분의 프로그래밍 언어의 기본
- (2) '출력 모드': 피호출자의 형식인수가 호출자의 실인수로 전달
- (3) '입출력 모드': 호출자의 피호출자 사이의 양방향 전달이 모두 발생
┗ 개념적 모델: "자료 이동 측면"에서 인수 전달 방식이 도식적으로 어떤 방식인지에 관한 모델
- '값 전달': 실인수 값을 물리적으로 복사하여 전달
- '참조 전달': 실인수의 값을 참조할 수 있는 참조 경로를 전달(주소값)
┗ 구현 모델: "구현 관점"에서 프로그래밍 언어가 "인수 전달"을 어떻게 구현하는지에 따른 모델
- '값 전달': 실인수 값을 형식인수로 복사하여 전달
- '결과 전달': 형식인수 값을 실인수에 복사하여 전달
- '값-결과 전달': 호출 시 실인수 값을 형식인수에 복사하여 전달 후 복귀 시 형식인수 값을 실인수에 복사하여 전달
- '참조 전달': 실인수에 대한 참조 경로 전달
- '이름 전달': 실인수 이름을 전달
[ 값 전달 ]
┗ "실인수 값"을 "형식인수"에 복사하여 전달
┗ 입력 모드와 인수 전달을 구현
┗ 대부분의 언어에서 채택
┗ 구현 방법 1: 데이터를 물리적으로 복사
- 인수 전달 효율성이 좋지 못함(예: 큰 배열)
-> 복사 하기 때문에 복사할 데이터의 양이 많으면 효율이 떨어짐
┗ 구현 방법 2: 참조 경로 전달 및 쓰기 금지
- 간접 참조에 따른 시간 부담
[ 결과 전달 ]
┗ 형식인수 값을 실인수에 복사하여 전달
┗ 출력 모드의 인수 전달을 구현
┗ 구현 방법 1: 데이터를 물리적으로 복사
- 인수 전달 효율성이 좋지 못함
- 복사 순서에 따라 결과라 달라질 수 있음
┗ 구현 방법 2: 참조 경로 전달 및 실인수의 초깃값 사용 금지
- '실인수의 주소 값 결정 시기': 대부분 호출 시 결정
[ 값-결과 전달 ]
┗ "호출 시" => 실인수 값을 형식인수로 복사
┗ "복귀 시" => 형식인수 값을 실인수로 복사
┗ 입출력 모드의 인수 전달을 구현
┗ 구현 방법: 두 번 모두 물리적으로 값을 복사
- 복사에 의한 전달 (pass-by-copy)
┗ 장점: 별칭 문제가 발생하지 않음
┗ 단점: 비효율을 비롯한 값 전달의 단점과 결과 전달읠 단점이 모두 포함
[ 참조 전달 ]
┗ "실인수의 주소(혹은 참조)"를 형식인수에 전달
- 실인수와 형식인수가 같은 변수
- 즉, '주소값'을 보내기 때문에 '동일한 변수'를 '공유'하는 개념임.
┗ 입출력 모드의 인수 전달을 구현
┗ 공유에 의한 전달
┗ 장점: 전달 과정 자체가 효율적
┗ 단점: 별칭 문제가 발생할 수 있음
┗ 별칭 문제:
- 한 대상을 다른 이름으로 지칭하여 발생하는 문제
- '발생 상황': 실인수 충돌, 배열 원소 충돌, 형식인수와 전역변수 충돌
void change(int *a, int *b) {
*a = 10;
*b = 20;
}
int x = 0;
change(&x, &x);
-> 서로 다른 a, b값에 &x 주소값이 들어가는 상황 -> 어떤걸 넣어야 될지 모름
[ 이름 전달 ]
┗ 실인수 이름을 전달:
- 형식인수 사용 시 실인수 이름이 사용됨
┗ 특정 모델에 대응하지 않음:
- '장점': 늦은 바인딩으로 인한 유연함
- '장점': 젠슨의 기법과 같은 범용 서브프로그램 작성 가능
- '단점': 인수 참조가 매우 비효율적
- '단점': 인수 전달 의미가 난해하여 이해하기 어려움
💡 3. 서브프로그램 관련 주제
[ 범용 서브프로그램 ]
┗ 범용 서브프로그램:
- 여러 용도로 사용할 수 있는 서브프로그램
- "다형" 서브프로그램과 "다목적" 서브프로그램
┗ 다형 서브프로그램:
- 여러 타입의 인수에 적용 가능한 서브프로그램
- 제너릭 서브프로그램
- C 언어: 매크로 확장을 이용
-> 인수 타입 검사 불가
- C++은 템블릿, Java는 제너릭 이용
-> '매개변수적 다형성': 타입 인수를 받아 여러 타입을 다룸
┗ 다목적 서브프로그램:
- 다양한 목적에 적용 가능한 서브프로그램
- '젠슨의 기법': 이름 전달의 늦은 바인딩을 이용
[ 분리 컴파일과 독립 컴파일 ]
┗ 각 모듈을 다른 프로그래머가 작성:
- 독자적으로 자신의 소스코드를 컴파일할 수 있어야 함
┗ 분리 컴파일:
- 코드 사이의 인터페이스 정보를 이용하며 프로그램 일부를 다른 부분과 분리하여 컴파일하는 방법
┗ 독립 컴파일:
- 인터페이스 정보 없이 프로그램 일부를 다른 부분과 분리하여 컴파일 하는 방법
┗ 주요 언어의 예:
- 'Fortran 2~77', 'C', 'C++': 독립 컴파일 지원
- 'Ada', 'Fortran 90', 'Modula-2': 분리 컴파일 지원
- 'Pascal': 독립 컴파일과 분리 컴파일 모두 지원하지 않음'방송통신대학교 > 📝 프로그래밍 언어론' 카테고리의 다른 글
| [프로그래밍 언어론] 12강 - 문장 (0) | 2026.09.11 |
|---|---|
| [프로그래밍 언어론] 11강 - 수식 (0) | 2026.09.11 |
| [프로그래밍 언어론] 10강 - 복합타입 (0) | 2026.09.10 |
| [프로그래밍 언어론] 9강 - 타입 (0) | 2026.09.08 |
| [프로그래밍 언어론] 8강 - 변수의 영역 (0) | 2026.09.06 |
