Study/Etc.

프로그래밍 언어론(Program Languages) 졸업 고사 정리

빨간당무 2010. 9. 28. 16:26
■ 바인딩(Binding)을 설명하고 바인딩시간(Binding time)의 종류 ([1] pp.221)
- 바인딩(Binding)
일반적인 의미에서, 속성과 개체 사이 또는 연산과 기호 사이와 같은 연관(Association)이다.
바인딩이 일어나는 시간을 바인딩 시간이라고 부른다. 바인딩과 바인딩 시간은 프로그래밍 언어 의미론에서 매우 중요한 개념이다. 
바인딩은 언어 설계 시간, 언어 구현시간, 컴파일 시간, 링크 시간, 적재 시간, 또는 실행 시간에 일어날 수 있다.

다음 C 배정문을 생각해 보자
int count;
count = count + 5;
위 배정문에 대해서 고려할 수 있는 바인딩과 바인딩 시간은 다음과 같다.
- count에 대한 가능한 타입의 집합은 언어 설계 시간에 바인딩 된다.
예) int, long, float 등등
- count의 타입은 컴파일 시간에 바인딩 된다. (책에 기술됨)
예) int에 대응
- count의 가능한 값들의 집합은 컴파일러 설계 시간에 바인딩 된다. (책에 기술됨)
예) int형 값의 범위 (-???? ~ +????)
- 연산자 기호 +에 대한 가능한 의미의 집합은 언어 구현 시간에 바인딩 된다.
예) 수치 연산과 문자열 결합
- 연산자 기호 +의 의미는 컴파일 시간에 피연산자의 타입이 결정되었을 때 바인딩 된다. (책에 기술됨)
예) 피연산자인 count와 5는 int형 이므로 수치 연산으로 바인딩
- 리터럴 5의 내부 표현은 컴파일러 설계 시간에 바인딩 된다. (책에 기술됨)
예) 바이트 코드로 00001001 로 표현
- count의 값은 이 배정문의 실행 시간에 바인딩 된다. (책에 기술됨)
예) count가 가리키는 메모리 공간에 5를 저장
 
- 바인딩 타임의 종류
- 바인딩이 일어나는 시기 또는 결정되는 시간을 말한다.
1. 언어 설계 시간
언어에서 허용되는 대부분의 자료구조나 프로그램 구조 등을 확정.
예) 혼합형 연산 허용 시 어떤 연산을 수행할 것인가 등을 확정.
2. 언어 구현 시간
언어 정의 시 원소에 대한 특성을 모두 한정치 않고 구현 시 일부 확정토록 일임.
대부분 언어들이 구현 시 바인딩을 최소화하여 특정기종에 구애받지 않도록 함.
예) 정수의 자리 수, 실수의 유효숫자 개수 등.
3. 컴파일 시간
정적 바인딩, 변수의 이름 또는 형과 프로그램 문장 구조 등 확정. 효율성 중시.
4. 링크 시간
부 프로그램 코드로 라이브러리에서 부 프로그램을 호출.
5. 적재 시간 
변수를 메모리 셀로 바인드 함.
6. 실행 시간
실행시간에 일어아는 바인딩. 변수의 값을 확정하거나 변수에 기억장소 할당.

■ 변수의 타입 바인딩 ([1] pp.222)
- 변수는 프로그램에서 참조될 수 있기 전에 데이터 타입에 바인딩되어야 한다. 
- 정적 타입 바인딩
바인딩이 실행시간 전에 일어나고, 프로그램 실행 과정에서 변하지 않는 상태로 유지되는 것
타입은 명시적 또는 묵시적 선언을 통해 정적으로 명세 될 수 있음
효율성을 중요시, 컴파일 언어
컴파일 시 대부분의 속성을 결정하여, 실행시간의 오버헤드를 줄이고자 함이 목적임
- 명시적 선언 : 변수의 이름을 나열하고, 이들을 특정 타입으로 명세하는 프로그램 문장
- 묵시적 선언 : 선언문 대신 기본(default) 규칙에 의해 변수에 타입 연관 (신뢰성이 덜어질 위험)
- 동적 타입 바인딩
바인딩이 실행시간 중에 일어나거나 프로그램 실행 과정에서 변경될 수 있는 것
타입이 선언문에 명세되지 않고, 배정문에서 변수에 값이 배정될 때 타입이 변수에 바인딩
좌변 = 우변 (우변의 타입이 동적으로 바인딩 됨)
융통성, 편리성을 중요시, 인터프리터 언어
장점으로는 프로그램의 유연성이 높아짐
단점으로는 컴파일러의 오류 탐지능력이 정적 타입 바인딩을 사용하는 언어 보다 떨어짐, 비용이 비쌈, 프로그램의 실행이 지연됨

■ 타입 호환성(type compatibility)과 장단점 ([1] pp.234)
- 타입 호환성
피연산자(operand)에 연산자(operator)가 바인딩(binding) 될 때 연산(operation)이 이루어 질 수 있도록 타입(type) 전환(conversion)함.

- 이름 타입 호환성(name type compatibility)
타입의 이름을 가지고 서로 호환될 수 있는지를 검사.
구현이 쉽고 신뢰성이 높다. 유연성이 떨어진다.
- 구조 타입 호환성(structure type compatibility)
변수의 타입의 구조가 같으면, 서로 호환될 수 있도록 해줌.
유연성은 높다. 구현이 어렵고, 신뢰성이 떨어진다.

- 이름 타입 동등(name type equivalence)
2개의 변수가 동일한 선언문에 속하거나 동일한 타입 이름으로 선언되면, 이 2개의 변수는 동등 타입을 갖는다는 것을 의미한다.
- 구조 타입 동등(structure type equivalence)
두 변수의 타입과 동일한 구조를 가지면, 이 두 변수는 동등 타입을 갖는다는 것을 의미한다.

■ 블록 구조 언어(block struct language)에서 정적 영역 규칙(static scope rule)을 설명 ([1] pp.241)
- 블록(block)
시행이 코드 세그먼트에 진입할 때, 변수에 대한 기억장소가 할당되고, 그 세그먼트를 빠져나올 때 그 기억장소가 회수된다. 이러한 코드 세그먼트를 블록이라고 한다.
블록에 의해서 생성된 영역은 부프로그램에 의해서 생성된 영역과 동일하게 취급된다. 만약, 블록에 선언되지 않은 변수 참조는 이 블록을 포함하는 영역을 그 크기가 증가하는 순서로 탐색하여 그 변수에 대한 선언을 찾는다.
- 블록 구조 언어(block structured language)
C-기반 언어는 복합문(중괄호에 둘러싸인 일련의 문장)이 선언문을 포함하는 것을 허용하며, 따라서 새로운 영역을 정의하는 것을 허용한다.
C++에서는 변수 정의가 함수의 어느 곳에도 올 수 있다. 
C++, Java, C#의 for 문에서는 그 초기화 식 상에 변수가 정의 가능한다. 
- 정적 영역 규칙
한 변수에 대한 참조를 발견할 때, 그 변수에 대한 속성을 그 변수가 선언된 문장을 찾아서 결정
- 동적 영역 규칙
부 프로그램들이 코드에 위치한 공간적 관계에 기반하지 않고 부 프로그램의 호출 순서에 기반(실행 시간에 결정)

- 예를 들어 아래와 같은 코드가 있을 때
program main : 
var x : integer;
procedure sub1;
begin
writeln('x', x);
end; {sub1}
procedure sub2;
begin
x := 10;
sub1;
end; {sub2}
begin {main}
x :=  5;
sub2;
end {main}
동적 영역 규칙 : x는 10이 됨 (sub1의 동적 조상은 sub2임)
정적 영역 규칙 : x는 5가 됨 (sub1의 정적 조상은 main임)

■ 참조환경에 대해서 설명 ([1] pp.247)
- 문장의 참조 환경(referencing environment)은 그 문장에서 가시적인 모든 이름들의 집합이다. 
정적 영역 언어에서, 문장의 참조 환경은 지역 영역에 선언된 변수들과 그 조상 영역에 속한 가시적인 모든 변수들로 구성된다. 이러한 언어에서, 문장의 참조 환경은 그 문장이 컴파일되고 있는 동안에 필요하며, 따라서 실행 시간 중에 다른 영역의 변수에 대한 참조를 가능하게 하는 코드와 데이터 구조가 생성될 수 있다. 

■ 데이터 타입(data type) ([1] pp.262)
- 데이터 타입은 데이터 값들의 모임과 이러한 값들에 대해서 미리 정의된 연산들의 집합으로 정의된다.

- 기본 데이터 타입(primitive data types)
다른 타입으로 정의되지 않은 데이터 타입
- 문자 스트링 타입(character) string type)
타입의 값이 일련의 문자로 구성되는 타입
- 사용자-정의 순서 타입(ordinal type)
순서 타입(ordinal type)은 가능한 값의 범위가 쉽게 양의 정수 집합과 연관될 수 있는 타입
열거 타입(enumeration type), 부분 범위 타입(subrange type)
- 배열 타입(array type)
동질적인 데이터 원소들의 집단체이며, 개개의 원소가 그 집단체(aggregate)의 첫 번째 원소와의 상대적 위치에 의해서 식별된다.
- 연상 배열(associative type)
키(key)라 불리는 동일한 개수의 값으로 인덱싱되는 순서를 갖지 않는 데이터 원소들의 모임
- 레코드 타입(record type)
개개의 원소가 이름으로 식별되는 이질적일 수 있는 데이터 원소들의 집단체. 레코드의 원소는 필드(field)이다.
- 공용체 타입(union type)
프로그램 실행 중에 다른 시기에 다른 타입의 값을 저장할 수 있는 타입
- 포인터와 참조 타입(pointer and reference type)
- 포인터 타입 : 변수가 메모리 주소와 특수 값 nil로 구성되는 값의 범위를 갖는 타입. nil은 유요한 주소가 아니며, 현재 사용 불가를 나타냄
- 참조 타입 : 포인터와 유사하나, 중요하고 근본적으로 다른 변수이다. 포인터는 메모리의 주소를 참조하는 것에 반해서, 참조 변수는 객체나 메모리의 값을 참조한다. 결과적으로 주소(포인터)에 대해서 산술 연산을 수행하는 것은 자연스럽지만, 참조에 대해서 산술 연산을 수행하는 것은 의미가 없다.

■ 문자 스트링(Character string) 타입(Type)의 저장 표현(Storage representation) ([1] pp.270)
- 문자 스트링 타입은 그 타입의 값이 일련의 문자들로 구성되는 타입이다.
1. 정적 길이 스트링(Static length string)
스트링 길이는 정적이고, 그 선언에서 명세될 수 있다. 
정적 길이 스트링은 상항 꽉 차있다.
만약 스트링 변수에 길이가 짧은 스트링이 배정되면 부족한 문자는 공백으로 채워진다.

2. 제한된 동적 길이 스트링 (Limited dynamic length string)
스트링이 가변 길이를 갖는 것을 허용한다.
이때 스트링의 최대 길이는 그 변수의 정의에 의해서 설정된 길이이다.
이러한 스트링 변수는 0부터 최대 길이까지 문자를 저장할 수 있다.
C와 C++의 스트링이 스트링의 길이를 유지하기 보다는 스트링의 끝을 나타내는 특수 문자를 사용한다.

3. 동적 길이 스트링 (Dynamic length string)
스트링이 최대 길이 없이 가변길이를 갖는 것을 허용한다.
이 선택은 동적 기억장소의 할당과 회수에 따른 부담을 요구하지만, 최대의 유연성을 제공한다.

■ 문자 스트링 타입의 구현 ([1] pp.271)
- 정적 길이 스트링(static length string)
정적 길이 스트링 타입에 대한 서술자는 단지 컴파일 과정에서만 사용되며, 다음 3가지 필드를 갖는다.
 정적 스트링
 길이
 주소

- 제한된 동적 길이 스트링(limited dynamic length string)
제한된 동적 스트링
최대 길이
현재 길이
 주소
C와 C++의 제한된 동적 스트링은 스트링의 끝이 널문자로 표시되기 때문에 실행 시간 서술자를 필요로 하지 않는다.

- 앞서 정적 길이 스트링과 제한된 동적 길이 스트링은 특별히 동적 기억장소 할당을 요구하지 않는다. 제한된 동적 길이 스트링의 경우에, 스트링 변수가 기억장소에 바인딩될 때 최대 길이에 충분한 기억장소가 할당된다. 따라서 단지 한번의 할당 과정이 포함된다. (최대 길이는 컴파일 시간에 고정됨)

- 동적 길이 스트링(dynamic length string)
동적 길이 스트링은 단지 현재 길이만 저장될 필요가 있으므로 더 단순한 실행 시간 서술자를 요구한다.
하지만, 동적 길이 스트링은 더 복잡한 기억장소 관리를 요구한다. 

- 동적 길이 스트링에 대해서 요구되는 동적 할당과 반환을 지원하는 두 가지 방법이 있다. (2? 3?)
1. 스트링은 연결 리스트에 저장될 수 있다.
따라서 스트링이 늘어날 때, 새롭게 요구된 메모리 셀은 힙으로부터 할당될 수 있다.
장점은 연관됨 할당과 회수 과정은 단순하다.
단점은 리스트 표현에서 링크가 차지하는 여분의 기억장소와 스트링 연산의 필연적인 복잡성이다.

2. 스트링을 힙에 할당된 개개의 문자들을 가리키는 포인터들의 배열로서 저장하는 것이다.
이 방법도 여전히 여분의 메모리를 사용하나, 스트링 처리는 연결 리스트 방법보다 더 빠를 수 있다.

3. 스트링 전체를 인접한 기억장소 셀에 저장하는 것이다.
이 방법의 문제점은 스트링이 늘어날 때 발생한다. 기존의 셀들에 인접한 기억장소가 그 스트링 변수에 대해서 계속 할당 될 수 없는 경우 발생 될 수 있다. 대신 새로운 스트링 전체를 저장할 수 있는 새로운 메모리 영역을 찾아야 하고, 스트링의 이전 부분이 새로운 영역으로 이동된다. 다음에 이전 스트링에 대해서 할당되었던 메모리 셀들이 회수된다. (전형적으로 사용됨)
장점은 더 빠른 스트링 연산이 가능하며, 상당히 더 작은 기억장소를 요구한다.
단점은 할당과 반환 과정이 느리다.

■ 배열(array) 타입의 구현을 서술 ([1] pp.277)
- 배열(array)
동질적인 데이터 원소들의 집단체이며, 개개의 원소가 그 집단체(aggregate)의 첫 번째 원소와의 상대적 위치에 의해서 식별된다.
배열
원소 타입  float
인덱스 타입 int
인덱스 하한 0 or 1
인덱스 상한 9 or 10
주소 &a or a
만약 float a[10]이라는 배열은 위에 1차원 배열에 대한 컴파일 시간 서술자로 표현 할 수 있다.

- 1차원 배열에서 원소 접근 함수 (일반화)
주소( list[k] ) = 주소( list[ 하한 ] ) + ( ( k - 하한 ) * 원소_크기 )

■ 함수적 부작용(side effect) ([1] pp.333)
- 함수적 부작용이라고 불리는 함수의 부작용은 함수가 자신의 매개변수나 전역변수를 변경할 때 발생한다. (전역 변수는 함수외부에 선언되어 있으나 함수에서 접근이 가능하다.)
- 다음 식을 생각해 보자
int a = 5;
int fun1() {
a = 17;
return 3;
} /* of fun1 */
void main() {
a = a + fun1();
} /* of main */
main 에서 계산된 a의 값은 식 a + fun1()에 포함된 피연산자들의 평가 순서에 따라 다르다. a의 값은 8(a가 먼저 평가되면)이거나 20(함수 호출이 먼저 평가되면)일 것이다.

■ 단락 회로 평가(short-circuit evaluation)의 장단점을 설명 ([1] pp.344)
- 식의 결과가 모든 피연산자와 (또는) 연산자를 평가하지 않고서도 결정되는 평가이다.
- 산술식에서 볼 때
( 13  * a ) * ( b / 13 - 1)
위 식의 값은 a가 0이면 (b/13-1)의 값에 관계없이 결정된다. 그러나 산술식에서 이러한 단락회로는 프로그램 실행 중에 쉽게 탐지되지 않는다.
- 관계식에서 볼 때
( a >= 0 ) && ( b < 10 )
위 식의 값은 a < 0이면 두 번째 관계식과는 무관하다. 이러한 단락회로는 실행 중에 쉽게 발견될 수 있다.
- C-기반 언어에서 보통의 AND와 OR 연산자, &&와 ||는 각각 단락회로이다. 단, 비트 단위 AND와 OR 연산자, &와 |를 각각 제공하는데, 이러한 연산자는 부울 피연산자에 대해서 사용될 수 있으나 단락회로는 아니다.

- 예를 들어 (표준) Pascal 의 경우에는 단락회로 평가를 사용하지 않는다.
Index := 1;
While ( ( index <= listlen ) and ( list[index] <> key ) do
Index := index + 1;
위 코드의 경우 마지막에 list의 상한 첨자값이 listlen의 범위를 초과하여 원소 인덱스 오류를 야기할 것이다.

- 예를 들어 Ada는 프로그래머가 and then과 or then의 연산자를 사용하여 단락회로 평가를 명세하는 것을 허용한다.
Index := 1;
while ( Index <= Listlen) and then ( List (Index) /= Key )
loop
Index := Index + 1;
end loop;
위 코드의 경우 Key가 List에 포함되지 않아 Index가 listlen보다 크게 될 경우에 오류를 야기하지 않는다.

■ 부 프로그램 ([1] pp.398, pp.410)
- 부 프로그램이란 프로그램의 여러 장소에서 명령어 카드의 묶음을 재사용하는 능력 (추상화)
- 매개변수는 부프로그램이 처리할 데이터에 접근하는 방법이다.
- 부 프로그램의 특성
- 각 부프로그램은 단일 진입점을 갖는다.
- 호출 프로그램 단위는 피 호출 부프로그램의 실행 중에 중단된다. 즉 임의의 주어진 시간에 수행중인 부프로그램은 꼭 하나이다.
- 부프로그램이 실행을 끝났을 때 제어는 항상 호출 프로그램에게 돌아간다.
- 매개변수 전달의 의미적 모델
- 입력 모드(in mode) : 형식 매개변수는 해당 실 매개변수로 부터 데이터를 받는다.
- 출력 모드(out mode) : 형식 매개변수는 데이터를 실 매개변수에 전달한다.
- 입출력 모드(inout mode) : 형식 매개변수는 실 매개변수로부터 데이터를 받고 또한 데이터를 실 매개변수에 전달한다. 
- 데이터 이동이 매개변수 전달에서 일어나는 방법
실제의 값이 물리적으로 이동하거나 접근 패스가 전달(단순 포인터)하는 방법이 있다.

■ 매개 변수 전송 방법 ([1] pp.410)
- 값-전달(pass-by-value)
입력모드의 의미를 구현함. 쓰기-보호에 효율적이고 편리한 방법. 스칼라 변수에 대해 연결 비용과 접근 시간 관점에서 빠르다는것. 단점은 형식 매개변수를 위해 부가적인 기억장소가 별도로 할당되어야 하며 기억장소와 복사연산은 매개변수가 많은 원소를 갖는 배열과 같이 크다면 비용이 많이든다.
-
매개변수가 값으로 전달할 때, 실 매개변수의 값은 해당 형식 매개변수를 초기화하기 위해 사용됨. 형식 매개변수는 지역 변수로 사용. 입력 모드 의미를 구현
- 결과-전달(pass-by-result)
출력 모드의 의미를 구현함. 매개변수가 결과로 전달될 때, 어느 값도 부프로그램으로 전달되지 않음. 해당 형식 매개변수는 지역 변수로 사용되지만, 제어가 호출자에게 반환되기 바로 전에 그 값은 호출자의 실 매개변수로 전달됨. 값 전달시 값-전달과 같이 부가적인 기억장소와 복사연산이 요구됨.추가적인 문제로 (sub(p1, p2))와 같이 실 매개변수가 충돌되는 경우, 함수내에서 배정하는 순서중 마지막에 배정하는 값으로 배정됨. 그리고 다른 매개변수-전달 방법에 사용될 때와 구현자가 실 매개변수의 주소 평가를 2개의 다른 시점(호출시 또는 복귀시) 중에 하나를 선택할 수 있다는 문제가 있다. (구현에 따라 이식성이 없게 됨)
-
출력 모드 매개변수에 대한 구현 모델, 매개 변수가 결과로 전달될 때, 어느 값도 부 프로그램으로 전달되지 않음, 실제 값 이동으로 구현
- 값-결과-전달(pass-by-value-result)
실제 값이 복사되는 입출력 모드의 의미를 구현함. 실재로는 값-전달과 결과-전달의 결합임. 실매개변수->형식매개변수->실매개변수로 복사되기 때문에 복사-전달(pass-by-copy)라고 불린다. 값-결과-전달의 장점은 참조-결과-전달의 상대적이다.
-
실제값이 이동하는 입출력 모드 매개변수의 구현모델 1번과 2번의 혼합방식, 복사 전달방법이며 다중 기억장소와 복사하는 시간이 요구됨
- 참조-전달(pass-by-reference)
입출력모드의 두번째 구현모델임. 값-결과-전달 처럼 값을 전달하는 것이 아니라 접근패스(주소)를 피호출 부프로그램에 전달함. 사실상, 피호출 부프로그램은 실매개변수를 공유한다. 장점은 전달과정 자체가 시간과 기억장소관점에서 효율적이다. (기억장소의 중복 없음, 복사 없음) 단점은 첫째, 형식 매개변수의 접근은 한 단계 이상의 간접주소를 요구하기 때문에 더 느리다. 둘째, 피호출 부프로그램에 한 방향 전달방법 만이 요구되는 경우, 부주의하고 오류적인 변화가 실 매개변수에 행해질 수 있다. 또한 별칭(alias)이 생성될 수 있다.
-
입출력 모드 매개변수의 형태로 접근 패스(주소)를 통해 피호출 부프로그램에 전달. 피 호출 부프로그램이 호출 프로그램에 있는 실 매개변수를 접근 가능. 공유하므로 시간과 공간의 효율성이 좋다.
- 이름-전달(pass-by-name)
단일 구현모델에 일치하지 않는 입출력 모드 매개변수 전달 방식이다. 이름-전달 형식 매개변수는 부프로그램 호출시에 접근 방법에 바인딩되지만 값이나 주소에 실제 바인딩은 형식 매개변수에 값이 배정되거나 참조될 때까지 연기된다. 컴파일 시간에 사용된다.
-
단일 구현 모델에 일치하지 않는 입출력 모드 매개변수 전달방식이다. 실 매개변수 형태가 이름-전달 매개변수의 구현 모델을 강요함. 프로그래머에게 유연성을 제공. 느림. 구현이 어려움

■ 활성화 레코드(activation record) 구조를 서술 ([1] pp.451)
- 부 프로그램의 비코드 부분의 형식, 즉 배치(layout)를 활성화 레코드라 한다. 
왜냐하면 이 부분이 서술하는 데이터는 부프로그램의 활성화, 즉 부 프로그램 실행과 관련이 되기 때문이다. 활성화 레코드의 형식은 정적이다. 활성화 레코드 사례(activation record instance; ARI)는 활성화 레코드의 구체적인 예이며 활성화 레코드 형식에 존재하는 데이터의 모임이다.
 지역 변수
 매개 변수
 복귀 주소
단순 부프로그램의 활성화 레코드

- 단순 부프로그램은 별도의 두 부분으로 구성된다. 즉 변하지 않는 부프로그램 코드와 부프로그램이 실행되는 동안 변할 수 있는 지역 변수와 위에서 열거한 자료들이다. 단순 부프로그램의 경우 둘 다 고정 크기를 갖는다.

■ 동적 체인, 정적 체인에 대해 설명 ([1] pp.457, pp.462)
- 동적 체인(dynamic chain)
주어진 시점에서 스택에 있는 동적 링크의 집합을 동적 체인(dynamic chain) 또는 호출 체인(call chain)이라 한다.
동적 체인은 실행이 현 지점(활성화 레코드가 스택의 top에 있는 프로시저 코드에 있는 지점)까지 도달한 동적 역사를 반영한다. 지역 변수의 참조는 코드에서 활성화 레코드의 시작 지점으로부터 지역 영역의 오프셋(offset)으로 나타낸다. 그런 오프셋을 지역 오프셋(local_offset)이라 한다. 

- 정적 체인(static chain)
스택의 어떤 활성화 레코드 사례들을 연결하는 정적 링크의 체인이다. 정적 체인은 정적 부모를 시작으로 실행 중인 부프로그램의 모든 정적 조상을 연결한다. 이 체인은 분명히 정적 영역 언어에서 비지역 변수의 접근을 구현하는 데 사용된다.

■ 추상화(abstract) 데이터 타입에 대해 설명 ([1] pp.478)
- 추상화는 중요한 속성만을 포함하는 개체의 개관 또는 표현이다. 
추상화는 개체들의 사례(instance)를 공통적인 속성이 고려될 필요가 없는 그룹으로 모으는 것을 허용한다. 즉, 이 공통된 속성들은 추상화 되어 제거된다.
추상화는 프로그래밍의 복잡성을 해결하는 방법이다. 추상화의 목적은 프로그래밍 과정을 단순화 하는 것이다. 
기초적인 두 가지 종류의 추상화는 프로세스 추상화와 데이터 추상화이다.

■ 예외 처리(exception handling) ([1] pp.609)
- 예외처리
디스크 읽기 오류와 같은 하드웨어에 의해 발견되는 오류와 end-of-file과 같은 비정상적인 상태를 예외(exception)라 칭한다.
예외의 개념을 확장하여 소프트웨어 탐지 가능한 오류 및 특이한 상태를 포함한다.
따라서 예외를 하드웨어나 소프트웨어적으로 감지될 수 있고 특별한 조치(processing)가 요구되는 오류일 수도 있고 아닐 수도 있는 독특한 이벤트(unusual event)로서 정의한다.
예외의 감지에 의해 요구되는 특별한 조치는 예외처리(exception handling)라고 불린다. 이 조치는 예외 처리기(exception handler)라 불리는 코드에 의해서 행해진다.
- 예외 처리기 
프로그래머가 예외 상황을 정의하였을 때 그것을 처리하는 동일한 동작 구조
- 예외 처리기를 내장할 때의 장점
- 오류 상태를 탐지하기 위한 코드 삽입으로 인한 프로그램 혼란 방지
- 예외 전파 : 예외가 정적 또는 동적 조상에서 사용되는 것을 허용 (프로그램 재사용성 증가)

■ 객체지향 언어의 세가지 특징 ([1] pp.516)
- 1. 추상 데이터 타입
객체를 구분되는 핵심적인 특징으로 분류한 것
중요한 속성만을 포함하는 개체의 개관 또는 표현이다. 추상화는 개체들의 사례(instance)를 공통적인 속성이 고려될 필요가 없는 그룹으로 모으는 것을 허용한다.
- 2. 상속
기존 객체에 새로운 기능이나 특성을 추가하여, 새로운 객체를 만드는 것을 의미 한다. 한 객체가 다른 객체의 특성을 이어받는 과정을 상속이라고 한다. (재사용성)
- 3. 메소드에 대한 메소드 호출의 동적 바인딩
여러 작용들 중에서 실제로 작용되는 것은 데이터 형에 의해 결정된다. 오버로딩이라고 할 수 있는데 같은 이름의 함수로 서로 다른 작업이 실행 가능하다.
메시지를 메소드 정의에 동적 바인딩에 의해서 제공되는 다형성이다. 목적은 소프트웨어 시스템이 개발과 유지보수 동안 쉽게 확장되는 것을 허용하는 것이다.
- 캡슐화
데이터와 이것을 조작하는 코드를 결합하여 외부의 접근으로부터 코드와 데이터를 안정하게 유지하는 메커니즘이다. 즉 객체는 캡슐화를 지원하는 도구라고 할 수 있다.
- 정보은닉화
캡슐속에 쌓여진 항목에 대한 정보를 외부에 감추는 것을 의미한다. 외부에서는 직접 접근하지 못하고 캡슐 내부의 함수들만이 접근 가능하다.

■ 오버로딩(overloading) ()
- 오버로딩
하나의 객체가 두 가지 이상의 개념으로 사용되는 경우
한 클래스 내에 같은 이름의 메소드를 여러 개 정의하는 것을 메서드 오버로딩
- 메서드의 이름이 같아야 한다.
- 매개변수의 개수 또는 타입이 달라야 한다.
- 매개변수는 같고 리턴타입이 다른 경우는 오버로딩이 성립되지 않는다.



2010년 02학기 예상 문제

활성화 레코드(Activation record)
단락회로 장점 단점(short-circuit)
정보 은닉
추상 데이터 타입(abstract data type)
코루틴(coroutine)
객체 지향의 특징(장점)
프로그램 언어의 의미(semantics - operational, axiomatic, denotation)
파라미터 전달 방법(parameter passing methods)
바인딩(binding)
참조 환경(reference environment0
함수 부작용
문자 스트링 타입 구조
배열 타입
정적, 동적 체인
포인터의 단점

■ 코루틴(coroutine) ([1] pp.441)
- 코루틴은 특별한 종류의 부프로그램이다. 전통적인 부프로그램에 존재하는 호출 부프로그램과 피호출 부프로그램의 주-종속 관계라기보다는 호출 코루틴과 피호출 코루틴은 좀 더 대등한 위치에 있다. 실제로 코루틴 제어 구조는 종종 대칭적 단위 제어 모델(symmetric unit control model)이라 불린다.
- 코루틴은 코루틴 자체에 의해서 제어되는 다중 진입점을 갖는다. 또한 코루틴은 활성화 사이에 상태를 유지하는 방법을 갖는다. 따라서 코루틴은 과거 민감형이며 정적 지역 변수를 갖는다. 
- 코루틴의 두 번째 실행은 가끔 처음이 아닌 지점에서 시작한다. 이런 이유로 코루틴의 시작은 호출(call)이라기보다는 리쥼(resume)이라고 불린다.
- 코루틴의 집합으로 해결할 수 있는 문제는 카드 게임의 시뮬레이션이다. 
- 코루틴은 다중 진입점을 갖는 특별한 부프로그램이다. 코루틴들은 부프로그램의 인터리브 실행(interleaved execution)을 제공하는데 사용된다.

■ 프로그램 언어의 의미(semantics - operational, axiomatic, denotation) ([1] pp.158, [2])
- 연산 의미론(operational semantics)
이상적인 기계에서 언어 구조의 의미를 그 효과의 관점에서 기술하는 방법이다.
-
기본적인 개념은 문장이나 프로그램을 더 쉽게 이해되는 언어로 번역함으로써 그 의미를 기술하는 것이다.
연산 의미론의 사용에는 여러가지의 수준이 있다. 가장 높은 수준에서, 관심은 완전한 프로그램 실행의 최종 결과에 있다. 이러한 수준의 사용을 때때로 자연적 연산 의미론(natural operational semantics)라고 한다. 가장 낮은 수준에서, 연산 의미론은 단일 문장에 대한 정확한 의미를 결정하는 데 사용될 수 있다. 이는 흔히 문장의 번역된 버전을 조사함으로써 가능하다. 이러한 수준의 사용을 때때로 구조적 연산 의미론(structural operational semantics)이라 한다.
-
연산 의미론의 기본 개념은 문장(statements)을 실제 기계(machines)나 모의 실험된 기계에서 실행시키므로서 프로그램의 의미를 기술 (주어진 문장을 수행할 때 기계의 상태 변화가 그 문장의 의미를 정의)
연산 의미론을 기술하기 위해서는 실제 컴퓨터(real computer)나 가상 컴퓨터(virtual computer)의 명령어를 사용하여 문장에 대한 알고리즘을 기술
예를 들어 C의 for 문의 연산 의미론은 아래와 같다.
C statement
for (expr1; expr2; expr3) {
   ...
}



연산 의미론
         expr1;
loop : if expr2 = 0 goto out
         ...
         expr3;
         goto loop
out : ...
연산 의미론은 서술이 단순하고 비형식적인 경우에 의미를 기술하는 효과적인 방법을 제공
- 공리 의미론(axiomatic semantics)
형식 논리에 기초하고 있으며, 프로그램 정확성을 증명하기 위한 도구로서 고안되었다.
-
프로그램의 정확성을 증명하는 방법의 개발과 연관하여 정의되었다. 이러한 정확성 증명은, 이것이 구성될 수 있을 때, 프로그램이 그 명세에서 기술된 계산을 수행한다는 것을 보여준다. 증명 과정에는, 프로그램에 포함된 각 문장의 앞과 뒤에, 프로그램 변수에 대한 제한 사항을 명세하는 논리식이 부여된다.
주목적은 프로그램의 정확성(correctness)를 증명하는 방법으로 개발
프로그램의 각 문장 전후에 변수간의 관게와 제약을 명시하는 논리식(단언:assertion, 서술:predicate)을 포함
공리적 방법(모든 문장 유형에 대해 공리와 추론 규칙을 정의하여 프로그래밍 언어의 의미론을 정의)
프로그램의 정확성을 증명하기 위한 강력한 도구
- 표기 의미론(denotation semantics)
수학적 객체가 언어 구조의 의미를 표현하는 데 사용된다. 언어 요소들은 이러한 수학적 객체로 재귀 함수를 통해서 변환된다.
-
프로그램의 의미를 기술하는 데 있어서 가장 엄격하고 널리 알려진 방법이다. 
이 의미론은 재귀 함수 이론(recursive function theory)에 견고하게 기반한다. 표기 의미론의 기본적인 개념은 각 언어 요소에 대해서 수학적 객체를 정의하고, 그 언어 요소의 사례를 정의된 수학적 객체의 사례로 사상하는 함수를 정의하는 것이다.
-
프로그램의 의미를 기술하는 가장 정밀한 방법
재귀 함수 이론에 근거
각 언어 요소에 대해 수학적 객체로 사상하는 함수를 정의
언어 설계에 도움을 주기 위해 사용
서술의 복잡성 때문에 거의 사용되지 않는다.
언어를 간명하게 서술할 수 있는 좋은 방법을 제공한다.

■ 포인터의 단점 ([1] pp.305)
- 포인터(pointer) 타입은 변수가 메모리 주소와 특수 값 nil로 구성되는 값의 범위를 갖는 타입이다. 값 nil은 유효한 주소가 아니며, 포인터가 메모리 셀을 참조하는데 현재 사용될 수 없음을 나타내는 데 사용된다.
- 포인터의 두가지 용도
1. 포인터는 어셈블리 언어 프로그래밍에서 상당히 많이 사용되는 간접 주소지정 능력을 제공한다.
2. 포인터는 동적 기억장소를 관리하는 방법을 제공한다. 포인터는 동적으로 할당되는 기억 장소 영역의 한 위치를 접근하는데 사용될 수 있다. 이러한 기억장소의 영역을 보통 힙(heap)이라 부른다.
- 포인터는 흔히 데이터를 저장하느 데 사용되기보다는 다른 변수를 참조하는데 사용된다.
- 포인터의 문제
- 허상 포인터(dangling pointer) 또는 허상 참조(dangling reference)
이미 회수된 힙-동적 변수의 주소를 포함하고 있는 포인터이다.
허상 포인터는 여러 가지 이유로 위험하다.
1. 가리키고 있는 기억장소 위치가 어떤 새로운 힙-동적 변수에 다시 할당되었을 수 있다.
2. 기억장소 위치가 가용 기억장소 블록들의 체인에 속한 포인터로서 기억장소 관리 시스템에 의해서 임시적으로 사용될 수 있고, 따라서 그 기억장소 위치의 값 변경은 기억장소 관리 시스템을 훼손시킬 가능성이 있다.
동적 변수의 명시적 회수는 허상 포인터의 원인임을 유의해야 한다.
- 분실된 힙-동적 변수(lost heap-dynamic variable)
사용자 프로그램에서 더 이상 접근될 수 없는 할당된 힙-동적 변수이다. 이러한 변수를 흔히 쓰레기(garbage)라 한다. 
- 분실된 힙-동적 변수는 흔히 다음 일련의 연산으로 생성된다.
1. 포인터 p1이 새롭게 생성된 힙-동적 변수를 가리키도록 설정된다.
2. p1이 나중에 또 다른 새롭게 생성된 힙-동적 변수를 가리키도록 설정된다.
첫 번째 할당된 힙-동적 변수는 이제 접근될 수 없다. 즉, 분실되었다. 이러한 문제를 때때로 메모리 누수(memory leakage)라고 부른다.



참고 문헌
1) 프로그래밍 언어론 (Concepts of Programming Language) 제 8판, Robert W. Sebesta 지음, 유원희, 하상호 옮김, 홍릉과학출판사, 2008
2) http://211.221.225.175/~comsys/PL_PDF/chapter3.pdf