1. 프로그래밍 언어 소개
- 프로그램이란 컴퓨터가 수행할 명령어를 순서대로 나열해 둔 것이며, 프로그래밍 언어는 프로그램 작성에 사용되는 언어이다. 프로그래밍 언어는 컴퓨터가 수행할 수 있고 사람이 읽을 수 있는 형태로 계산을 나타내는 표기체계이다.
- 프로그래밍 언어는 말이 아닌 글 형태로 사용되고, 엄밀한 규칙에 따라 정의되며, 주로 기계에 명령을 전달하는 단방향 언어이다.
- 언어는 우리의 사고 능력과 밀접한 관련이 있으며 프로그래밍은 우리에게 체계적으로 생각하는 방법을 가르쳐 준다.
- 프로그래밍 언어의 기본적인 기능은 작성력과 가독성, 실행 가능성으로 요약할 수 있다.
- 프로그래밍 언어는 추상화, 모듈화를 지원한다.
- 프로그래밍 언어는 기계적, 구조적, 가변적이라는 특성을 지닌다.
- 프로그래밍 언어는 추상화 수준에 따라 저급언어부터 고급언어까지 다양한 스펙트럼으로 존재하는데, 고급언어란 기계에 독립적인 언어를 뜻한다.
- 프로그래밍 언어는 데이터, 연산, 명령어, 서브프로그램, 타입, 모듈 등으로 구성된다.
- 프로그래밍 언어는 구문론과 의미론을 통해 정의할 수 있다.
- 프로그래밍 언어를 선택할 때는 자신의 사전지식을 고려해야 하며 실제로 사용해 볼 수 있는 언어, 프로그램을 관리하기 쉬운 언어, 자신의 업무와 관련 있는 언어, 자신이 아는 언어와 유사한 언어를 선택하는 것이 바람직하다.
- 프로그래밍을 배우기 위해서는 ‘눈보다 손’으로 학습해야 하고, 그림을 통해 생각하면 더 편리하며, 간단한 프로그램부터 시작하여 복잡한 프로그램으로 점진적으로 변경하는 것이 좋다.
- 프로그래밍 언어론을 배우는 이유는 새로운 언어를 쉽게 배우기 위해서, 또 내가 사용하는 언어를 더 잘 이해하기 위해서, 나아가 궁극적으로 현명한 언어 설계자가 되기 위해서이다.
2. 프로그래밍 언어의 발전 및 동작원리
- 저장 프로그램 방식의 에드박이 등장하면서 프로그램이라는 개념이 등장하게 되었다.
- 1950년대 초기 프로그래밍 언어로 Fortran은 수식 계산, 변수, 대입문, 함수, 제어문의 초기 형태를, Algol은 제어 구조 개념을, LISP는 함수형 언어 개념을 소개하였다.
- 1960년대 발표된 Cobol은 레코드를 통한 자료 구조 개념을 제시하였다. BASIC은 교육용 언어로서 큰 인기를 끌었으며 Simula는 객체지향 개념을 처음 소개하였다.
- 1970년대 가장 영향력이 높은 프로그래밍 언어는 C이다. Pascal은 구조화 프로그래밍의 교육용 언어로 자리잡았고, 그 외 다양한 패러다임의 언어가 등장하였다.
- 1980년대에는 객체지향 개념이 더욱 견고해지고 다양한 언어 표준이 이루어졌다.
- 1990년대에는 Java와 JavaScript, Python을 필두로 하여 프로그래밍 언어의 대중화가 시작되었다.
- 인터프리터는 고급언어 프로그램으로 작성된 문장을 하나씩 읽어서 수행한다. 컴파일러는 고급언어 프로그램을 기계어로 미리 번역한다. 하이브리드 구현은 고급언어 프로그램을 중간 코드 형태로 컴파일하고 이 중간 코드를 가상기계 상에서 해석한다.
- 프로그래밍 언어의 요구사항을 효과적으로 지원하기 위해 따라야 하는 프로그래밍 언어 설계 원칙으로는 규칙성, 추상화 지원, 복잡도 지원 등을 들 수 있다.
- 프로그래밍 언어의 평가 기준 중 대표적인 것으로 작성력, 가독성, 신뢰성, 직교성, 일관성, 확장성, 효율성, 유연성, 이식성 등을 들 수 있다.
- 프로그래밍 언어를 선택할 때는 언어 사용 커뮤니티가 활발하고 호의적인지, 언어의 특정 응용 분야가 있는지, 새로운 프로그래밍 패러다임을 지원하는지 등을 고려해야 한다.
3. 프로그래밍 언어 패러다임
- 프로그램을 작성하는 전형적인 방식을 프로그래밍 패러다임이라고 부른다.
- 명령형 프로그래밍 패러다임에서 프로그램은 특정 작업을 수행하기 위해 명령어가 나열된 것이다. 컴퓨터 하드웨어의 속성을 그대로 반영한 형태의 패러다임이다.
- 절차형 프로그래밍 패러다임은 문제를 해결하기 위한 절차를 서브루틴 단위의 절차로 구현하는 방식의 패러다임으로, 프로그램을 절차의 집합으로 간주한다.
- 함수형 프로그래밍 패러다임에서는 데이터를 값으로 간주하고, 주어진 데이터로부터 새로운 값을 생성하는 함수에 초점을 맞추어 프로그램을 작성한다.
- 논리 프로그래밍 패러다임에서는 문제의 조건을 논리식으로 표현하고 이 식을 바탕으로 어떤 사실을 입증해 나가는 방식으로 프로그램을 수행한다. 논리 프로그래밍 패러다임은 선언적 프로그래밍 패러다임의 일종이다.
- 객체지향 프로그래밍 패러다임은 데이터와 관련 연산을 합쳐 객체로 모형화하고, 객체 사이의 상호작용을 통해 프로그램을 수행하는 프로그래밍 패러다임이다.
- 프로그래밍 패러다임의 변화 배경으로는 응용 도메인의 변화, 프로그램 구성 방식의 변화, 계산 모델의 변화 등을 들 수 있다.
- 하나의 프로그래밍 언어가 한 패러다임만 지원하는 것은 아니다.
- 구조화 프로그래밍은 goto 논란으로부터 촉발되었는데 goto 없이 프로그램을 작성하는 패러다임이다.
- 다양한 프로그래밍 패러다임은 서로 배타적이라기보다 상호 보완적인 것으로 보는 것이 바람직하다.
4. 구문론과 의미론
- 프로그래밍 언어는 문장을 정확하게 이해할 수 있도록 명확한 구문과 그 의미가 정의되어야 한다. 이를 프로그래밍 언어의 형식적 정의라 하며 이는 다시 구문론과 의미론으로 나눌 수 있다.
- 구문론은 프로그램의 표면적인 구조를 정의하는 것으로, 프로그램 작성 시 어떤 형태로 작성해야 하는지를 기술한다.
- 의미론은 프로그램의 내용적인 효과를 정의하는 것으로, 프로그램 실행 시 어떤 일이 일어나는지 그 의미를 기술한다.
- 프로그래밍 언어에서 구문은 문맥 자유 문법으로 표현된다. 문맥 자유 문법이란 문맥에 영향을 받지 않는 문법을 의미한다.
- 문맥 자유 문법을 표현하는 방법으로 BNF, EBNF, 구문 도표가 있다.
- 프로그래밍 언어에서 의미는 자연어로 표현되는 경우가 많지만, 엄밀한 표현을 위한 형식 의미론도 존재한다.
- 형식 의미론에서 다루는 표현 방법으로는 속성 문법, 기능적 의미론, 표기적 의미론, 공리적 의미론이 있다.
5. 구문 분석
- 프로그램의 분석은 크게 어휘 분석과 구문 분석으로 나눌 수 있다.
- 어휘 분석을 통해 프로그램에서 사용된 단어인 토큰을 구별해 낸다. 토큰의 종류에는 연산자, 구분자, 식별자, 예약어 등이 있다.
- 식별자는 변수나 함수 등의 이름을 나타내는 토큰이다.
- 예약어는 프로그래밍 언어 자체에 정의되어 포함된 토큰으로 사용자 재정의가 불가능하다.
- 유도는 구문 규칙을 이용하여 주어진 프로그램을 만들어 내는 과정으로, 유도가 가능하다면 주어진 프로그램은 문법적 오류가 없다.
- 파스 트리는 유도를 트리 형태로 나타낸 것으로, 루트 노드는 시작 비단말 기호, 단말 노드는 단말 기호가 된다. 단말 노드를 왼쪽부터 오른쪽으로 차례로 나열하면 주어진 프로그램이 된다.
- 주어진 표현에 대한 파스트리가 존재하면 구문에 부합하는 표현이지만, 파스 트리가 존재하지 않으면 오류가 있는 표현이다.
- 모호한 문법은 동일한 표현에 대해 서로 다른 파스 트리가 만들어지는 문법으로, 하나의 프로그램이 서로 다른 결과를 도출할 수 있는 위험을 내포하고 있다.
- 모호한 문법은 문법을 명확하게 변경하여 모호성을 제거해야 한다.
6. 프로그래밍 언어의 구현
- 프로그래밍 언어를 구현하기 위해서는 먼저 언어를 정의해야 하며, 이는 프로그램의 형태를 정의하는 구문론과 프로그램의 수행 의미를 정의하는 의미론으로 정의할 수 있다.
- 프로그래밍 언어 구현은 함수 모델로 해석할 수 있다.
- 전통적인 프로그래밍 언어는 기계의 단순한 명령어를 확대하는 형태로 구현한다. 그러나 새로운 패러다임의 프로그래밍 언어는 구현 모델을 추상기계로 만들고 이를 징검다리로 삼는 형태로 구현한다.
- 추상기계와 가상기계의 차이는 해당 기계의 구체적인 구현물이 있는지 여부이다.
- 컴파일러의 구현 단계는 크게 분석 단계와 생성 단계로 나눌 수 있다. 프로그래밍 언어에 의존적인 분석 단계를 전단부, 목적 기계에 의존적인 생성 단계를 후단부라고 부른다.
- 인터프리터를 구현할 때도 컴파일러의 전단부에 해당하는 분석 단계는 그대로 거친다. 하지만 전단부에서 생성된 중간 표현을 목적 코드로 바꾸는 대신 중간 표현을 순회하며 프로그램을 실행한다.
- 구문 트리와 중간 표현 외에 프로그래밍 언어 구현에 필요한 자료 구조로는 심볼 테이블과 환경을 들 수 있다.
- 언어 구현 시에는 프로그램이 실행되는 환경인 실행 환경도 고려해야 한다.
- 어휘 분석기는 어휘의 토큰과 속성을 분석하며, 구문 분석기는 토큰을 이용하여 구문 트리를 구성한다. 구문 트리는 파스 트리와 추상 구문 트리의 두 가지 형태가 있다.
7. 변수와 바인딩
- 변수란 데이터를 저장하거나 나중에 사용할 수 있도록 메모리를 추상화한 것이다.
- 변수의 속성에는 변수명, 타입, 주소, 값이 있다. 변수의 값은 수행시간 동안 바뀔 수 있다.
- 바인딩이란 언어 구성 요소의 속성이 구체적으로 결정되는 것을 의미한다.
- 바인딩 시각이란 언어 구성 요소의 속성이 결정되는 시점을 의미한다. 바인딩 시각은 크게 정적 바인딩과 동적 바인딩으로 구분된다.
- 변수의 바인딩은 변수의 속성이 구체적으로 결정되는 것을 의미한다. 즉, 변수명 바인딩, 타입 바인딩, 주소 방인딩, 값 바인딩이 해당된다.
- 변수의 변수명 바인딩 방법과 타입 바인딩 방법에는 명시적 선언과 묵시적 선언이 있다.
- 변수의 정적 타입 바인딩은 컴파일 시점에 구문 분석을 통해 타입을 판단하고, 동적 타입 바인딩은 수행 시점에 대입할 값에 맞추어 타입을 판단하기에 계속 변할 수 있다.
- 변수의 수명은 변수가 메모리를 할당받고 있는 기간이다.
- 변수의 주소 바인딩 방법에는 자동 할당과 수동 할당이 있다.
- 변수의 정적 주소 바인딩은 로드 시점에 정적 세그먼트의 주소를 바인딩하고, 동적 주소 바인딩은 수행 시점에 동적 세그먼트의 주소를 바인딩한다.
- 정적 주소 바인딩을 하는 변수를 정적 변수, 동적 주소 바인딩을 하는 변수를 동적 변수라고 한다. 동적 변수는 스택 동적 변수와 힙 동적 변수로 나누어진다.
8. 변수의 영역
- 변수의 영역이란 프로그램에서 변수를 사용할 수 있는 범위를 의미한다.
- 블록은 영역을 구분해 주는 단위로, 프로그램 문장들의 묶음이면서 그 안에서 변수 선언이 가능하다.
- 지역변수는 블록 안에서 선언된 변수이고, 비지역변수는 블록 밖에서 선언되었지만 블록 안에서 사용될 수 있는 변수이다.
- 참조 환경은 한 위치에서 사용할 수 있는 모든 변수의 모음으로, 해당위치의 모든 지역변수와 모든 비지역변수로 구성된다.
- 영역 규칙은 변수의 참조 위치를 결정하는 방법이다. 특히 현재 블록에서 선언되지 않은 자유변수에 대해 어디에서 선언된 비지역변수인지 혹은 오류인지 확인한다.
- 정적 영역 규칙은 블록들의 정적 내포 관계를 이용하여 변수의 참조 위치를 찾는 방법으로, 컴파일 시점에 결정할 수 있다. 동적 영역 규칙은 블록들의 동적 내포 관계를 이용하며, 수행 시점에 결정할 수 있다.
- 영역 구멍은 비지역변수가 같은 이름의 지역변수 때문에 보이지 않는 영역을 의미한다.
- 정적 영역 규칙은 동적 영역 규칙에 비해 안정적이고 수행 속도가 빨라서 대부분의 언어에서 사용한다.
- 전역변수는 어떤 블록에도 포함되지 않는 곳에서 선언된 변수로 영역은 프로그램 전체가 된다.
- 이름 공간은 관련성이 높은 변수와 함수를 하나의 묶음으로 관리하는 영역으로, 변수명처럼 영역 자체의 이름을 갖는다. C++는 이름 공간을 지원한다.
9. 타입
- 타입은 데이터 집합과 연산 집합의 결합이다. 데이터 집합은 처리 대상이 되는 데이터들의 집합이고, 연산 집합은 해당 데이터에 적용 가능한 연산의 집합이다.
- 프로그램 내 모든 연산 및 함수에 대해 적용 전후의 타입이 연산 및 함수의 정의와 일치한다면 그 프로그램은 타입 안전하다고 한다.
- 강타입 언어는 프로그램에 존재하는 모든 타입 오류를 검출해 내고, 약타입 언어는 일부 타입 오류를 허용한다. 무타입 언어는 타입 선언문이 없고 어떤 대상의 타입이 계속 바뀔 수 있다.
- 타입의 정의에 사용자가 개입할 수 있는지 여부에 따라 원시타입과 사용자정의타입으로 분류한다.
- 데이터 요소의 형태에 따라 단순타입과 복합타입으로 분류한다. 단순타입에는 정수형, 실수형, 문자형, 논리형, 열거형이 있다.
- 정수형은 정수 데이터를 다루는 타입으로, 데이터 집합에 포함되는 정수의 범위에 따라 다양한 타입이 존재한다. 연산 집합에는 사칙연산, 나머지 연산, 비트 연산, 관계 연산 등이 포함된다.
- 실수형은 실수 데이터를 다루는 타입으로, 데이터 집합에 포함되는 실수의 범위는 지수부와 가수부의 범위에 따라 달라진다. 연산 집합에는 사칙연산, 관계 연산 등이 포함된다.
- 문자형은 하나의 문자 데이터를 다루는 타입으로, 데이터 집합에 포함되는 문자의 범위는 ASCII 코드, 유니코드 등에 따라 달라진다. 연산 집합에는 관계 연산 등이 포함된다.
- 논리형은 참과 거짓의 두 논리 데이터를 다루는 타입으로, 연산 집합에는 논리 연산이 포함된다.
- 열거형은 순서 관계가 있는 이름들을 데이터로 다루는 타입으로 사용자정의타입이다. 데이터 집합에는 사용자가 지정한 이름들이, 연산 집합에는 관계 연산 등이 포함된다.
10. 복합타입
- 배열은 동질형 데이터의 모음으로 구성된 타입으로, 원소는 첨자로 구별한다. 차원은 배열에 사용되는 첨자의 개수이다.
- 배열은 첨자를 통해 원소의 주소를 쉽게 찾아야 한다. 2차원 이상의 배열은 저장 순서에 따라 행우선 저장 방법과 열우선 저장 방법이 있다.
- 문자열형은 문자열 데이터를 다루는 타입으로, 데이터 집합은 모든 문자열이 모인 집합이다. 연산 집합에는 언어에 따라 대입 연산, 연결 연산 등이 포함된다.
- 연관배열은 동질형 데이터의 순서 없는 모음으로 구성된 타입으로, 원소는 키로 구별한다. 데이터 집합은 모든 키 타입 데이터와 원소 타입 데이터의 쌍을 포함한다. 연산 집합에는 개별 원소에 대한 연산들이 포함된다.
- 구조체는 다양한 타입의 데이터의 모음으로 구성된 타입으로, 원소는 이름으로 구별한다. 데이터 집합은 원소의 개수와 각 원소의 타입에 따라 다양하게 존재한다. 연산 집합에는 초기화, 대입 연산 등이 포함된다.
- 공용체는 저장공간을 공유하는 데이터의 모음으로 구성된 타입으로, 한 원소의 값이 바뀌면 다른 원소들의 값도 영향을 받는다. 원소는 이름으로 구별하며, 데이터 집합은 각 원소의 타입에 따라 다양하게 존재한다. 연산 집합은 개별 원소 타입의 연산 집합을 따른다.
- 포인터형은 특정 데이터가 저장되는 주소 자체를 데이터로 다루는 타입으로, 특정 데이터의 타입은 사용자가 지정한다. 데이터 집합은 가용한 범위의 주소를 포함하며, 연산 집합에는 대입 연산, 덧셈, 뺄셈 연산 등이 포함된다.
- 참조형은 사용자가 지정하는 타입의 데이터가 저장된 주소 자체를 자신의 주소로 사용하는 타입이다. 데이터 집합과 연산 집합은 지정한 타입을 따른다.
11. 수식
- 수식이란 피연산자와 연산자로 구성되어 하나의 값을 나타내는 표현이다.
- 수식은 값을 나타내는 표현이며 문장은 처리를 나타내는 표현이다.
- 산술 연산자에는 사칙 연산자 외에도 언어에 따라 나머지 연산자, 부호 연산자 등이 포함된다.
- 피연산자의 개수에 따라 단항 연산자와 이항 연산자가 있고, 언어에 따라 삼항 연산자도 있다.
- 하나의 수식에 여러 연산자가 사용되는 경우 정해진 우선순위에 따라 연산을 수행한다. 같은 우선순위의 연산자들이 섞여 있는 경우에는 결합방향에 맞춰 연산을 수행한다.
- 결합방향에는 좌결합과 우결합이 있다. 같은 우선순위의 연산자들 중 좌결합은 가장 왼쪽 연산자부터, 우결합은 가장 오른쪽 연산자부터 연산을 수행하는 방법이다.
- 타입 변환은 주어진 타입의 값을 다른 타입의 값으로 변환하는 것으로, 묵시적 타입 변환과 명시적 타입 변환이 있다.
- 관계 연산자는 2개의 피연산자를 서로 비교하여 둘 사이의 관계가 관계 연산자와 일치하는지 여부를 확인한다. 관계 연산의 결과 값은 참 또는 거짓이다.
- 논리 연산자에는 논리곱 연산자, 논리합 연산자, 부정 연산자 등이 포함된다. 논리 연산의 피연산자와 결과 값은 참 또는 거짓이다.
- 논리 연산의 경우 단락 평가를 통해 모든 논리 연산을 수행하지 않고도 수식의 값을 얻을 수 있다.
12. 문장
- 문장이란 처리를 나타내는 표현으로, 선언문과 실행문으로 구분할 수 있다.
- 선언문은 변수나 서브프로그램을 이용할 수 있도록 준비를 해 준다.
- 실행문은 실제적으로 변수도 이용하고 서브프로그램도 이용하며 데이터를 처리한다. 실행문에는 변수의 값을 변경하는 대입문과 프로그램의 수행 흐름을 제어하는 제어문이 있다.
- C, C++, Java에서 대입문은 변수에 대입된 값을 나타내는 수식에 쌍반점을 찍어 만든 문장이다.
- C++는 조건 연산자를 이용하여 값이 대입될 변수를 선택할 수도 있다.
- C, C++, Java는 다양한 복합 대입 연산자를 지원한다. 또한 단항 대입 연산자도 있다.
- 대입문에서의 묵시적 타입 변환은 대입할 값의 타입을 변수의 타입으로 변환한다. 단, Java는 확대변환인 경우만 묵시적 타입 변환이 일어나고, 축소변환이 필요한 경우는 명시적 타입 변환을 이용해야만 오류가 발생하지 않는다.
- 조건문은 조건에 따라 서로 다른 처리를 하도록 제어하는 문장이다.
- 반복문은 원하는 문장을 반복해서 수행하도록 제어하는 문장이다.
- while문은 반복문장이 한 번도 수행되지 않을 수도 있지만, do-while문은 반복문장이 적어도 한 번은 수행하게 된다.
13. 서브프로그램 개요
- 서브프로그램은 독자적인 입력과 출력을 갖춘 프로그램 조각으로 모듈화 프로그래밍을 지원하기 위해 기본적으로 필요한 기능이다.
- 서브프로그램으로 들어가는 입구는 일반적으로 하나인 반면 출구는 여러 곳이 될 수 있다.
- 서브프로그램은 반환값의 유무에 따라 프로시저와 함수로 분류할 수 있다. 프로그래밍 언어 개발 초기에는 반복적으로 사용되는 명령어 묶음을 서브루틴이라고 불렀다.
- 서브프로그램의 매개변수 개수, 순서, 타입을 매개변수 프로파일이라고 부르며 시그니처라고도 한다.
- 서브프로그램의 매개변수 프로파일과 함수 반환 타입을 합쳐 서브프로그램 프로토콜이라고 부른다. 정적 타입 언어의 경우 서브프로그램의 호출 전에 서브프로그램 프로토콜이 선언되어 있어야 한다.
- 외부로부터 전달될 정보를 받기 위해 서브프로그램 정의 부분에서 선언한 변수를 매개변수라 하고, 서브프로그램 호출 시 매개변수로 전달될 의도로 사용된 수식을 인수라고 한다. 매개변수를 형식인수(형식매개변수), 인수를 실인수(실매개변수)라고도 한다.
- 인수 전달의 의미적 모델로는 입력, 출력, 입출력 모드 세 가지가 있고, 개념적 모델로는 값 전달, 참조 전달이 있다. 구현 모델로는 값 전달, 결과 전달, 값-결과 전달, 참조 전달, 이름 전달이 있다.
- 입출력 모드 인수를 지원하기 위한 참조 전달은 별칭 문제를 발생시킬 수 있는데, 값-결과 전달을 이용하면 별칭 문제가 해결된다.
- 여러 용도로 가능할 수 있는 서브프로그램을 범용 서브프로그램이라고 하며 이는 다형 서브프로그램과 다목적 서브프로그램으로 구성된다.
- 모듈화 및 협업을 위해서는 분리 컴파일이나 독립 컴파일 기능이 필요하다.
14. 서브프로그램 구현
- 서브프로그램 호출과 복귀를 합쳐 서브프로그램 연결이라고 부르며 이때 제어 흐름뿐 아니라 자료 흐름도 관리해야 한다. 자료 흐름을 관리하기 위해 활성 레코드를 사용한다.
- 활성 레코드에는 서브프로그램의 데이터뿐 아니라 호출자의 상태, 복귀 주소, 반환값, 각종 관리 데이터가 저장된다.
- 초기 언어에서는 정적 활성 레코드 할당 방법을 사용했으나 이는 재귀호출이 불가능하다. 현재는 대부분 동적 활성 레코드를 사용한다.
- 활성 레코드에는 영역 규칙을 구현하기 위해 동적 링크와 정적 링크가 주로 사용된다.
- 정적 링크가 연결된 정적 체인은 정적 영역 규칙을 구현하기 위해 사용되고, 동적 링크가 연결된 동적 체인은 동적 영역 규칙을 구현하기 위해 사용된다.
- 정적 체인을 거슬러 올라가는 부담을 줄이기 위해서 디스플레이를 활용할 수 있다.
- 동적 영역 규칙에서 모든 변수에 대한 정보를 한곳에서 관리하며 변수를 참조하는 방법을 얕은 참조라고 한다. 얕은 참조에는 변수 스택 방법과 중앙 테이블 방법이 있다.
- 과거 민감 서브프로그램이란 이전의 호출 내용을 기억하는 서브프로그램이다.
- 코루틴이란 여러 개의 진입 지점을 스스로 관리하는 서브프로그램을 뜻한다. 코루틴은 ‘호출된다’고 하지 않고 ‘재개된다’고 한다.
15. 객체지향과 다형성
- 추상화란 복잡한 대상을 간략하게 나타내는 것을 뜻하는데, 이는 프로그래밍에 필수적인 작업이다.
- 프로그래밍 언어에서 제공하는 추상화 종류는 크게 제어 추상화와 자료 추상화로 나눌 수 있다.
- 여러 요소를 하나의 단위로 묶을 수 있는 기능을 캡슐화라 하고, 구현 세부 사항을 외부에 숨기고 인터페이스만 외부에 공개하는 기능을 정보 은닉이라고 부른다.
- 자료 집합과 적용 가능한 연산을 함께 선언한 타입을 추상 자료형이라고 한다.
- 객체란 특정 상태를 유지하며 외부 요구에 반응하는 행태를 보이는 대상을 추상화시킨 것이다.
- 객체에 따라 호출 메소드가 결정되도록 하기 위해서는 호출 메소드의 늦은 바인딩이 필요한데, 가상함수 테이블(VTab)로 늦은 바인딩을 구현한다.
- 여러 타입의 데이터를 같은 이름으로 처리할 수 있는 특성을 다형성이라고 한다.
- 다중 상속을 지원하면 다이아몬드 상속 문제가 발생한다.
- 객체를 직접 생성할 수 없을 정도로 극도로 추상화된 클래스를 추상 클래스라고 한다.
- 추상 클래스의 개념을 확장한 것으로 인터페이스와 트레잇을 들 수 있다.
연습 문제
1. 구문론이 아닌 프로그래밍 언어의 특징은 무엇인가?
- 프로그램의 표면적 구조를 정의한다.
- 문맥 자유 문법을 사용한다.
- 프로그램 실행 시 어떤 일이 일어나는지를 정의한다.
- BNF, EBNF, 구문 도표로 표현한다.
정답: 3
해설: 구문론은 프로그램의 표면적 구조를 정의하지만, 프로그래밍 언어의 의미론은 프로그램 실행 시 어떤 일이 일어나는지를 정의한다.
2. 어휘 분석의 목적은 무엇인가?
- 프로그램을 문법적으로 올바른지 검사한다.
- 프로그램에서 사용된 단어인 토큰을 구별한다.
- 프로그램의 실행 효과를 정의한다.
- 프로그램의 실행 환경을 설정한다.
정답: 2
해설: 어휘 분석은 프로그램에서 사용된 단어인 토큰을 구별하는 과정이다.
3. 프로그래밍 언어의 구현에서 추상기계와 가상기계의 차이점은 무엇인가?
- 추상기계는 실제 구현물이 없고 가상기계는 실제 구현물이 있다.
- 추상기계는 분석 단계에, 가상기계는 생성 단계에 사용된다.
- 추상기계는 컴파일러에 의존적이고, 가상기계는 인터프리터에 의존적이다.
- 추상기계는 함수 모델로 해석되고, 가상기계는 형식 의미론으로 해석된다.
정답: 1
해설: 추상기계는 구체적인 구현물이 없는 반면, 가상기계는 실제로 구현된 구체적인 구현물을 가진다.
4. 변수의 타입 바인딩 방법 중 정적 타입 바인딩의 특징은 무엇인가?
- 실행 시점에 타입을 결정한다.
- 컴파일 시점에 타입을 결정한다.
- 수행 시점에 계속 변할 수 있다.
- 사용자가 타입을 지정한다.
정답: 2
해설: 정적 타입 바인딩은 컴파일 시점에 타입이 결정되며, 이후에는 변경되지 않는다.
5. 변수의 영역에서 정적 영역 규칙의 특징은 무엇인가?
- 실행 시점에 결정된다.
- 동적 내포 관계를 이용한다.
- 블록들의 정적 내포 관계를 이용한다.
- 변수 스택 방법을 사용한다.
정답: 3
해설: 정적 영역 규칙은 블록들의 정적 내포 관계를 이용하여 변수의 참조 위치를 결정한다.
6. 타입의 분류에서 복합타입에 해당하지 않는 것은 무엇인가?**
- 배열
- 문자열형
- 정수형
- 구조체
정답: 3
해설: 복합타입은 다양한 타입의 데이터를 포함하는 타입을 의미한다. 정수형은 단순타입에 속한다.
7. 다음 중 문장과 수식의 차이점은 무엇인가?
- 문장은 처리를 나타내고, 수식은 값만을 나타낸다.
- 문장은 선언문과 실행문으로 구분되고, 수식은 피연산자와 연산자로 구분된다.
- 문장은 프로그램의 실행 효과를 정의하고, 수식은 구문의 구조를 정의한다.
- 문장은 언어의 의미를 정의하고, 수식은 언어의 형태를 정의한다.
정답: 1
해설: 문장은 프로그램의 처리를 나타내는 표현이고, 수식은 하나의 값을 나타내는 표현이다.
8. 서브프로그램 연결 시 사용되는 활성 레코드에 저장되지 않는 것은 무엇인가?
- 호출자의 상태
- 복귀 주소
- 서브프로그램의 데이터
- 프로그램의 실행 환경
정답: 4
해설: 활성 레코드에는 서브프로그램의 데이터, 호출자의 상태, 복귀 주소 등이 저장되지만, 프로그램의 실행 환경은 저장되지 않는다.
9. 객체지향 프로그래밍의 특징 중 캡슐화에 해당하지 않는 것은 무엇인가?
- 여러 요소를 하나의 단위로 묶는다.
- 구현 세부 사항을 외부에 숨긴다.
- 호출 메소드의 늦은 바인딩을 지원한다.
- 인터페이스만 외부에 공개한다.
정답: 3
해설: 캡슐화는 여러 요소를 하나의 단위로 묶고 구현 세부 사항을 숨기는 것이지만, 호출 메소드의 늦은 바인딩은 다형성과 관련된 특징이다.
10. 논리 연산자 중 부정 연산자(NOT)의 기능은 무엇인가?
- 두 피연산자가 모두 참일 때 참을 반환한다.
- 두 피연산자 중 하나라도 참이면 참을 반환한다.
- 참을 거짓으로, 거짓을 참으로 변환한다.
- 두 피연산자의 참/거짓 관계를 비교한다.
정답: 3
해설: 부정 연산자(NOT)는 참인 피연산자를 거짓으로, 거짓인 피연산자를 참으로 변환하는 기능을 한다.
11. 가비지 컬렉션의 주요 목적은 무엇인가?
- 메모리 할당을 최적화한다.
- 사용하지 않는 메모리를 자동으로 회수한다.
- 프로그램의 실행 속도를 향상시킨다.
- 메모리 누수를 방지한다.
정답: 2
해설: 가비지 컬렉션은 사용하지 않는 메모리를 자동으로 회수하여 메모리 관리를 도와준다.
12. 다형성을 구현하는 주요 방법은 무엇인가?
- 오버로딩
- 오버라이딩
- 캡슐화
- 추상화
정답: 1, 2
해설: 다형성은 하나의 인터페이스에 여러 객체가 대응될 수 있도록 하는 것으로, 오버로딩(같은 이름의 서로 다른 메소드)과 오버라이딩(상속받은 메소드의 재정의)을 통해 구현된다.
13. 프로그래밍 언어에서 동적 타입 결정의 특징은 무엇인가?
- 컴파일 시점에 타입을 결정한다.
- 실행 시점에 타입을 결정한다.
- 변수 선언이 필요하지 않다.
- 실행 시 타입 변경이 불가능하다.
정답: 2, 3
해설: 동적 타입 결정은 실행 시점에 타입이 결정되며, 이는 변수 선언 없이도 가능하다.
14. 컴파일러와 인터프리터의 주요 차이점은 무엇인가?
- 컴파일러는 전체 코드를 한 번에 번역한다.
- 인터프리터는 코드를 한 줄씩 실행한다.
- 컴파일러는 실행 파일을 생성한다.
- 인터프리터는 빠른 실행을 지원한다.
정답: 1, 2, 3
해설: 컴파일러는 전체 코드를 한 번에 번역하여 실행 파일을 생성하는 반면, 인터프리터는 코드를 한 줄씩 실행하며, 빠른 실행보다는 유연한 코드 수정이 장점이다.
15. 객체지향 프로그래밍에서 상속의 주요 목적은 무엇인가?
- 코드 재사용
- 메모리 절약
- 실행 속도 향상
- 데이터 보호
정답: 1
해설: 상속은 코드 재사용성을 높이고, 클래스 간의 관계를 명확히 하는데 주로 사용된다.
16. 런타임 오류와 컴파일 타임 오류의 차이점은 무엇인가?
- 런타임 오류는 프로그램 실행 중 발생한다.
- 컴파일 타임 오류는 컴파일 과정에서 발생한다.
- 런타임 오류는 주로 논리적 오류에 의해 발생한다.
- 컴파일 타임 오류는 구문 오류에 의해 발생한다.
정답: 1, 2, 4
해설: 런타임 오류는 프로그램 실행 중 발생하며, 컴파일 타임 오류는 컴파일 과정에서 구문 오류 등으로 발생한다.
17. 렉시컬 스코핑과 다이나믹 스코핑의 차이점은 무엇인가?
- 렉시컬 스코핑은 컴파일 시 결정된다.
- 다이나믹 스코핑은 실행 시 결정된다.
- 렉시컬 스코핑은 프로그램의 텍스트 구조에 의존한다.
- 다이나믹 스코핑은 호출 스택에 의존한다.
정답: 1, 2, 3, 4
해설: 렉시컬 스코핑은 컴파일 시 프로그램의 텍스트 구조에 따라 결정되며, 다이나믹 스코핑은 실행 시 호출 스택에 따라 결정된다.
18. 프로그래밍 언어에서 '정적 링크(Static Link)'의 용도는 무엇인가?
- 동적 메모리 할당을 관리한다.
- 서브프로그램의 지역 변수에 접근한다.
- 서브프로그램 간 정적 영역 규칙을 구현한다.
- 프로그램의 실행 환경을 설정한다.
정답: 3
해설: 정적 링크는 서브프로그램 간 정적 영역 규칙을 구현하는 데 사용된다. 이는 서브프로그램이 다른 서브프로그램의 변수에 접근할 수 있도록 하는 링크이다.
19. 인터프리터에서 '중간 표현'의 역할은 무엇인가?
- 소스 코드를 바이너리 코드로 변환한다.
- 소스 코드를 분석하고 구조화한다.
- 실행 시 실제 기계어로 변환한다.
- 프로그램 실행을 위해 소스 코드를 순회한다.
정답: 4
해설: 인터프리터에서 중간 표현은 프로그램 실행을 위해 소스 코드를 순회하는 역할을 한다. 이 과정에서 프로그램이 실행되며, 실제 기계어로의 변환은 발생하지 않는다.
20. 프로그래밍 언어에서 '디스플레이(Display)'의 목적은 무엇인가?
- 사용자 인터페이스를 제공한다.
- 정적 영역 규칙의 효율을 개선한다.
- 프로그램의 출력을 화면에 표시한다.
- 동적 영역 규칙을 관리한다.
정답: 2
해설: 디스플레이는 정적 영역 규칙의 효율을 개선하기 위해 사용된다. 이는 정적 링크를 통한 변수 접근 시, 정적 체인을 통한 탐색 과정을 최적화하는 데 도움을 준다.
21. '코루틴(Coroutine)'의 특징 중 올바른 것은?
- 단일 진입 지점을 가진다.
- 여러 진입 지점을 가진다.
- 항상 메인 프로그램에 종속된다.
- 재귀 호출이 불가능하다.
정답: 2
해설: 코루틴은 여러 진입 지점을 가지며, 이를 통해 다양한 지점에서 실행을 중단하고 재개할 수 있다. 이는 코루틴이 독립적으로 여러 작업 흐름을 관리할 수 있음을 의미한다.
'CS > 프로그래밍언어론' 카테고리의 다른 글
구문론과 의미론 용어 정리 및 연습 문제 풀이 - 프로그래밍 언어론 (1) | 2023.12.08 |
---|---|
방송대 프로그래밍 언어론 기출문제 오답률 높은 문제들 정리 및 해설 (1) | 2023.12.08 |
프로그래밍 언어 패러다임 (0) | 2023.10.09 |
프로그래밍 언어의 평가 기준 (0) | 2023.10.09 |
메모리에 적재된 프로그램의 기계어 명령어 하나를 컴퓨터의 CPU가 수행하는 과정 (1) | 2023.10.09 |