언어와 컴파일러
언어의 등장 순서 (기출)
연도 | 언어 |
---|---|
1956년 | 포트란 |
1958년 | Lisp |
1960년 | Algol , COBOL |
1970년 | Pascal |
1972년 | Smalltalk, Prolog, C(K&R) |
1980년 | Ada |
1985년 | C++ |
1990년 | Python |
1995년 | Java, Javascript |
2000년 | C#, Python 2.0 |
2004년 | java5 |
2008년 | Python3 |
2009년 | Go |
2010년 | Rust |
2011년 | Kotlin |
2012년 | Typescript |
2014년 | java8, Swift |
2018년 | java10 |
언어 | 언어 창시자 |
---|---|
Fortran | 존 배커스 |
Pascal | 니클라우스 워스 |
Java | 제임스 고슬링 |
c | 켄 톰슨 & 데니스 리치 |
LISP | 존 매카시 |
새로운 언어가 등장하는 이유
- 이론과 기술의 진화
- 특수 목적 언어의 등장
- Lisp: 자료구조
- Icon, Awk: 문자열 처리
- C: 로우 레벨 시스템 프로그래밍
- Prolog: 데이터 간의 논리적 관계를 추론 (p => ~q)
- 개인적 선호도
- 재귀스타일: 함수형 언어 선호
- 간결함: 파이썬같은 언어 선호
언어 설계의 두가지 관점
프로그래머 관점
- 알고리즘을 표현하는 수단, 개념의 명확성과 작성의 용이성
- 구현의 세부 사항을 신경쓰지 않게 vs 원하는 바대로 제어가 가능해야
- 컴파일러가 좋은 알고리즘을 찾아서 해결할 수 없는 경우 프로그래머가 명시적으로 정해주어야 함
구현 관점
- 컴파일러가 효율적으로 구현가능한 언어
언어의 성공 요인
언어 이론을 반영한 좋은 설계
- 자바(객체지향), 파이썬(최신 언어의 개념 반영), 스칼라(함수)
유용한 라이브러리 보급
- c, 자바, 파이썬
확실한 활용 분야 / 지원 기관
- Ada(국방), 자바스크립트(웹프론트)
컴퓨팅 환경의 변화에 적합
- 자바(웹의 확장), 파이썬(다양한 플랫폼 프로토타이핑), Kotlin, swift, go(모바일 표준 언어, 네이티브언어(성능 전력))
언어의 분류기준 (기출)
선언적언어(Declarative language)
컴퓨터가 무슨일(What)을 할 것인가를 기술하는 언어
절차형 언어(Procedural Language) 또는 명령형 언어(Imperative language) 또는 폰 노이만(본뉴만) 언어 <-> 함수형 언어
컴퓨터가 어떻게(How) 주어진 일을 처리할 것인지를 기술하는 언어
계산이 순차적으로 진행되므로 폰 노이만 병목 현상을 일으킨다.
많은 자료에 동시 적용될 수 있는 계산, 비결정적인 계산, 순서에 의존적인 계산에 취약하다.
이러한 문제를 해결하기 위해 나온것이 함수형 언어와 선언형 언어
계산예시) a = i; // a에 i를 넣음
예) Fortran, Ada, C
스크립트언어(Scripting languages)
- 독립적인 요소들을 엮어 목적을 달성하는 방식
- 빠른 프로토타이핑이 장점
- 실행속도나 성능 보다는 쉬운 표현력을 위주로 설계
- 특수목적언어: csh, bash, PHP, Javascript
- 범용목적언어: Perl, Python, Ruby
- 자바스크립트는 스크립트 언어여서 즉시 해석되고 실행되는 특징을 가지기는 하지만 이것도 최근에는 성능을 높이기 위해 컴파일 방식을 도입하기도 한다. 또한 특수목적 스크립트 언어라고 하기에는 너무나 많은 분야에서 광범위하게 쓰이고 강력한 기능을 제공하고 있다.
- 최근 자바스크립트는 중간코드를 사용, 브라우저를 가상머신처럼 사용하는 시도가 계속되고 있다(JIT 컴파일).
객체지향언어(Object-oriented languages:OOL) <-> 절차형 언어
폰 노이만을 기반으로 발전되었지만 엄밀히 말해서 폰 노이만 언어가 아니게 되었다!
- 계산은 세부 객체들 간의 상호작용으로 이루어짐
- 순수한 의미의 객체지향언어 : 스몰토크(SmallTalk)
- 예) C++, Java(초기 버전), C#
함수형 언어 또는 적용형 언어(Applicative Language)
재귀적 함수 정의에 바탕을 두는 프로그래밍 언어
계산예시) a.append(i); // a에 i를 넣음
예) Modula-2, Lisp, ML, Rust, Haskell, Scheme, Scala, Swift, 절차형 Go, Kotlin
논리형 언어 또는 선언형 언어(Declarative Language) (논리 또는 제약기반 언어)
술어논리(predicate logic)를 활용하여 계산의 내용만을 선언하듯이 기술한다.
예) Prolog, SQL 데이터베이스 언어
절차형 함수형 언어의 중간모델
예) PYTHON, python3, Typescript, JAVASCRIPT, JAVA8, java10, Go
동시언어
동시성은 구현에 의해 얻어지는 성질임
소스 수준 번역
컴파일하기 전에 번역을 한다
- 타입스크립트 -> 자바스크립트
- 코틀린 -> 안드로이드자바
- c++ -> c
컴파일러 <-> 중간모델 <-> 인터프리터
해석(interprete)은 프로그래머가 작성한 코드를 해석기(interpreter)가 읽는 즉시 바로 해석하여 실행하는 방식이고, 컴파일(compile)은 프로그래머가 작성한 코드를 컴파일러(compiler)가 목적 프로그램(윈도우의 경우 PE 포맷, 리눅스는 ELF 포맷) 기계어 코드로 변환한 뒤 기계어를 실행하는 방식이다. 해석은 생각한것을 즉시 실행하여 좀더 프로그래머에게 친숙한 언어라는 장점이 있고, 컴파일에 걸리는 시간이 적을 경우 컴파일은 프로그램의 실행 속도가 해석보다 빠르다는 장점이 있으나 컴파일에 걸리는 시간이 클 경우에는 해석이 더 나은 퍼포먼스를 보이기도 한다.
C,C++ 등등: 컴파일러
초기 AT&T C++ 컴파일러는 소스코드를 c언어로 파싱 -> c 컴파일러로 컴파일 과정을 거침
JAVA, C#: 중간모델
자바나 코틀린 같은 경우, 컴파일을 하면 JVM(Java Virtual Machine)이 이해할 수 있는 바이트코드(P-code:precompiled code)로 바뀌어, 가상머신 위에서 프로그램이 실행되면 JVM이 바이트코드를 내부에서 처리하는 형태의 바이트코드 컴파일러를 사용한다.
PYTHON, Javascript: 인터프리터
JIT 컴파일러
C나 C++에서 하는 것처럼 프로그램을 실행하기 전에 처음 한 번 컴파일하는 대신, 프로그램을 실행하는 시점에서 필요한 부분을 즉석으로 컴파일하는 방식을 JIT 이라고 한다. 보통 인터프리터 방식의 언어 구현들이 성능 향상을 목적으로 도입하는 경우가 많은데, JIT 컴파일러는 같은 코드를 매번 해석하는 대신 처음 실행될 때 인터프리트를 하면서 자주 쓰이는 코드를 캐싱한 뒤, 이후에는 캐싱된 코드를 가져다 쓰기 때문에 인터프리터의 느린 실행 속도를 개선할 수 있다. 따라서 사실 JIT ‘컴파일러’보다는 JIT ‘인터프리터’가 더 정확한 표현이다. 바이트코드 컴파일을 사용하는 Java도 바이트코드를 기계어로 번역할 때 JIT 컴파일러를 사용한다. 프로그램 구동시 소스 코드(혹은 바이트코드)를 실행 단계에서 컴파일하는 데에 시간과 메모리를 소모하기 때문에 정적 컴파일된프로그램에 비해 실행 속도 면에서 손해를 보게 된다. 크게 나눠서 HotSpot VM과같이 메소드(함수) 단위로 JIT 컴파일을 하는 방식과, 그보다 더 작은 단위에서 프로그램 실행 흐름을 실시간으로 추적하며 컴파일 할 코드를 탐색하는 Tracing JIT 방식으로 분류할 수 있다. 특히 Tracing JIT의 경우에는 실행 시점에만 알 수 있는 정보를 컴파일에 적극적으로 반영하기 때문에 이론적으로는 정적 컴파일 방식보다 더 빨라질 수도 있다. LISP, Java HotSpot VM, NET CLR (C# 등의 .NET Framework 계열 언어), LLVM, LuaJIT (Lua), PHP 8.0, PyPy (Python), TraceMonkey, V8, 차크라코어 (JavaScript), Dalvik VM (Java, 안드로이드)[5], 플래시 (액션스크립트 3.0), Julia, MATLAB, SQL (Prepared Statement 사용 한정) 등이 Jit 컴파일러를 지원한다.
네이티브 컴파일러
C언어의 경우 고급 언어를 컴파일 시 각 기계의 네이티브(cpu, 운영체제)에 맞는 실행 코드로 번역하여 기계어로 만드는 네이티브 컴파일러를 사용한다.
크로스 컴파일러
다른 cpu나 운영체제에서 작동하는 실행코드를 만들기 위하는 컴파일러로 크로스 컴파일러가 있는데, 안드로이드나 아이폰에서 구동할 앱을 위해 윈도우, iMac에서 swift나 kotlin으로 개발하는 것, 리눅스에서 ARM 전용 임베디드 시스템 커널을 구현하기 위해 ARM용 gcc를 사용하는 것 등이 모두 크로스컴파일러에 해당된다.
언어 분석
어휘 분석
공백(탭, 스페이스) 제외한 모든 단어나 기호 (엔터는 불확실)
종류: 기호, 키워드, 숫자, 문자열, 이름, 코멘트의 짝이 맞지 않을 때 /* */
결과물: 토큰(Token) 목록
구문 분석
변수 타입, 변수 이름, 초기화 부분
함수 몸체부 : 문장의 연속
결과물: 파스트리
파스 트리
프로그램의 구조와 각 부분의 역할을 나타내는 트리
언어의 구문을 기술하는 방법 : Context-Free Grammar
파서가 하는 일: 파스 트리를 만들면서 토큰의 순서와 규칙을 점검
의미 분석
이름의 올바름을 분석과 검사
동일한 이름인지 판별하고 여러 번 나오는 경우 일관되게 사용되고 있는지 검사함
타입 검사 : 수식이나 매개변수, 이름 등이 맞는 타입인가
의미분석 -> 의미 오류 검사
- C 언어
- 의미분석 단계에서 검사되는 의미 규칙 예
- 모든 이름은 사용되기 전에 반드시 선언되어야 함
- Undefined name 오류
- 같은 이름은 범위 안에서는 한번만 사용되어야 함
- Redefined name 오류
- 이름은 타입에 맞게 사용되어야 함
- 타입 오류: int를 배열이 필요한 자리에 넣거나
- 배열인덱스에 소수점수가 나타남
- 구조체가 아닌 것에 점이나 화살표를 붙임
- 함수 호출은 선언부와 일치해야 함
- 매개변수 개수와 타입이 맞지 않음
- 반환값이 반환형에 일치해야 함
- 반환값의 타입이 반환형과 다른 경우
결과물: 심볼 테이블(Symbol Table)
심볼 테이블
모든 이름에 대해 관련 정보를 모아 놓은 테이블
타입, 구조/크기, 범위
IR(Intermediate Representation)
파싱과 분석의 결과, 컴파일러가 코드를 생성하기 위한 정보의 집약체
Abstract Syntax Tree (AST) + Symbol Table
코드 생성기
심볼 테이블을 이용하여 프로그램의 정적 변수의 주소 할당 (고정된 주소 할당) - static 변수 포함
정적 변수를 제외한 것들은 오프셋 할당 (나중에 오프셋에 일정 값을 더해 실제 주소로 씀)
중간 표현을 검사하면서 기계어 명령문을 생성
변수의 참조를 위하여 로드 또는 저장 (레지스터 <-> 메모리)
비교 또는 수식 연산 명령문을 생성
검사에 의한 점프 명령문 생성 (점프할 위치의 레이블 생성)
결과물: 중간코드
코드 개선 또는 최적화(Optimization)
프로그램을 동일한 결과를 보장하면서 더 효율적으로 동작하는 버전으로 변환함
효율성 : 속도 개선 및 메모리 절약
- 코드 개선의 단계
- AST 상태에서 코드개선
- 코드 생성 이후 최적화
- 기계 독립적인 최적화
- 기계 의존적인 최적화
코드생성 전 AST 상태에서 코드 개선
코드의 의미에 따라 성능 개선이 가능한 변경
- AST 상태의 코드 개선방법 예
- 공통수식 부분 : 같은 계산이 반복되면 결과를 임시값으로 저장했다가 그대로 사용
- 불필요한 계산 : 계산 결과가 쓰이지 않으면 계산할 필요 없다
- 연산 바꾸기 : 곱하기 2는 좌측쉬프트, 나누기 2는 우측쉬프트로 바꾼다 (효율적인 연산으로 변경)
- 루프 불변식 : 루프 안에서 루프와 상관없는 계산이 있으면 루프 밖으로 꺼낸다
기계 독립적 코드 개선
특정 기계어 코드의 특성에 상관없이 수행되는 코드개선
변수의 불필요한 load/store를 모두 제거 – 레지스터에 그대로 두고 그 값을 그냥 사용
명령문 스케쥴링 - 데이터가 로드되기를 기다리는 동안 다른 명령문을 먼저 수행
기계 의존적 코드 개선
기계의 특성이나 명령문의 성질을 이용하는 최적화
특정 패턴을 이용한 코드 전체의 분석 방법
행렬 계산이나 플로팅포인트 계산에 특화된 명령문이 있는 경우 그것을 사용하도록 생성된 명령문을 대치
프로그램에서 다음 사항들이 결정되는 시점을 쓰시오.
int a = 123b;
어휘분석 - 이름
if(a = = 0)
구문분석
a = 5#4
어휘분석 - 기호
선언되지 않은 이름이 사용됨
의미분석 - 이름
같은 이름이 두 번 선언됨
의미분석 - 이름
{...괄호가 닫히지 않음
구문분석
int형 변수에 double형 값을 지정
의미분석 - 타입
매개변수 개수가 맞지 않음
의미분석 - 매개변수
초기화되지 않은 변수를 수식에 사용
실행시점
객체의 private 필드를 접근
의미분석
0으로 나누기
실행시점
바인딩(Binding)
정의
속성과 개체 사이 또는 연산과 기호 사이와 같은 연관(Association) 이름을 속성에 연관(bind)시키는 과정
바인딩 시간(Binding Time)
바인딩이 일어나는 시간
컴파일 시간
컴파일 언어의 원시 프로그램에 사용된 변수의 수명을 결정한다.
연계시간(Linkage Edit)
주프로그램에서 부프로그램으로 연결해야 할 변수들의 기억장소의 주소 등을 결정한다.
적재(Load) 시간
실행 가능한 프로그램이 Loader에 의해 기억장소에 적재될 때 각 변수에 해당하는 기억장소가 할당된다.
정적 바인딩 (Static Binding)
컴파일 바인딩, 번역시간 바인딩, 이른 바인딩(early binding)
언어 설계 시간
c언어
int count;
count = count + 5;
키워드, 구문, 함수 호출 방법, 흐름 제어 구조, 기본 (primitive) 타입의 종류, 복합 타입을 만드는 방법의 바인딩이 결정된다.
count에 대해 가능한 자료형을 전부 바인딩(int, char, long, float …)
리터럴 5의 내부 표현 (00000101) 바인딩
언어 구현시간
c언어
int count;
count = count + 5;
컴파일러를 개발하면서 바인딩이 결정된다.
실행 환경과 컴파일러에 따라서 달라지는것들
C: 기본 타입의 프리시젼(Precision), 실행시간 예외의 처리 방법
공통: 명령문 종류와 구조, 레지스터 사용방식, 라이브러리 환경, 스택과 힙의 최대 크기와 구조, 언어의 특정 기능을 처리하는 방식
예) +에 대해 가능한 의미의 집합 (컴파일러의 의미 분석 단계에 해당한다.)
예2) count가 가질 수 있는 값들의 집합 바인딩 (int형 범위)
컴파일 시간(compile)
c언어
int count;
count = count + 5;
변수 이름에 대응하는 타입, 메모리 크기, 순서
파일 내의 함수나 변수 이름에 대응하는 메모리 상대주소 등
예) count에 해당하는 자료형 바인딩 (int), +가 해당하는 의미 바인딩 (수치)
링크 시간(link)
분리 컴파일, 라이브러리 (stdio.h) 등을 호출
로드 시간(load)
- c언어
int count;
count = count + 5;
(변수 count에 대한 실제 메모리 값을 할당, 실제 주소 바인딩 )
동적 바인딩 (Binding Time)
실행시간 바인딩, 늦은 바인딩(late binding)
언어 설계, 언어 구현, 컴파일, 링크, 로드
결정되는 것 : 변수의 수명, 기억 공간 크기, 자료구조
실행 시간
- c언어
int count;
count = count + 5;
(count의 값(count + 5 한 값)이 주소에 바인딩된다.)
- 자바스크립트
count = 5;
(실행과 동시에 count의 자료형이 정해진다)
- 그 외
virtual function(가상 함수) table
정적 바인딩과 동적 바인딩은 실행시간을 기점으로 나뉜다.
정적 오류
어휘, 의미, 구문분석, 전처리, 코드개선 등 컴파일 단계에서의 모든 오류를 말한다.
동적 오류
실행 시 발생하는 모든 오류를 말한다.
- Java는 동적 검사에 의해 예외(Exception)를 발생시키는 방식으로 처리
- C는 동적 오류를 검사하지 않음(Segment Fault), 오류 검사가 정의되어 있지 않음.
바인딩의 범위 규칙
정적 범위 규칙
int a = 10;
void first(int b){
a = b;
write(a);
}
void second(int b){
a = 0;
first(a);
a = 2;
}
void main(){
int a;
a = input(); // 50
second(a);
write(a);
자신에게 없는 변수를 호출할 때는 정적 영역의 값을 우선으로 가져오는 것이 정적 범위 규칙이다.
보통 이는 program main의 값을 가져오는 것으로 규정한다. (위 코드에서 정적 영역은 int a = 10 이라고 친다.)
위와 같은 sudo 코드가 있다고 하자.
input을 받아 (50) main의 지역변수 a에 저장하고, second를 호출하면 second의 매개변수 b에는 50이 저장되게 된다. 그 뒤 a = 0 구문에서는 정적 변수(전역 변수) a가 0이 된다.
first 함수를 호출하면 first의 매개변수 b에는 0이 저장되고, a=b를 하게 되면 a에도 0이 write(a)를 하면 0이 출력된다.
마지막으로 second 함수의 a=2가 실행되면 전역 변수 a에 값 2가 저장된다.
다시 main함수로 돌아와 write(a)를 하면 50이 출력되게 된다.
동적 범위 규칙
int a = 10;
void first(int b){
a = b;
write(a);
}
void second(int b){
a = 0;
first(a);
a = 2;
}
void main(){
int a;
a = input(); // 50
second(a);
write(a);
자신에게 없는 변수를 찾을 때 바로 윗단계의(나를 호출한) 함수에서 변수값을 가져오는 것이 동적 범위 규칙이다.
만약 윗단계의 함수에도 선언된 변수가 없을 경우 다음 단계의 함수를 계속 탐색하며, 최종적으로 정적 영역을 탐색하게 된다.
위와 같은 sudo 코드가 있다고 하자.
input을 받아 (50) main의 지역변수 a에 저장하고, second를 호출하면 second의 매개변수 b에는 50이 저장되게 된다. 그 뒤 a = 0 구문에서는 호출한 main의 지역 변수 a가 0이 된다.
first 함수를 호출하면 first의 매개변수 b에는 0이 저장되고, a=b를 하면 윗단계 함수인 second를 탐색했을때 a가 없으므로 더 윗단계인 main 함수를 탐색해서 main의 지역변수 a에 b의 값인 0을 저장한다. write(a)를 하면 0이 출력된다.
마지막으로 second 함수의 a=2가 실행되면 main의 지역 변수 a에 값 2가 저장된다.
다시 main함수로 돌아와 write(a)를 하면 2가 출력되게 된다.
프로그램에서 다음 사항들이 결정되는 시점을 쓰시오.
①바인딩 생성 ②바인딩 사용 ③바인딩해지 ④객체생성 ⑤객체해지
1) (자바)힙 객체의 생성과 바인딩 순서 m = new M();
2) 지역변수 객체의 생성과 바인딩 순서 int n;
3) 매개변수로 전달된 참조변수의 생성과 바인딩 순서 void f(M m);
C 언어에서객체의종류와사용방법에관한설명이다. 틀린것을모두고르시오.
1)static 지역변수는정적객체이고함수가시작될때주소가할당된다. (틀렸음, 주소는 프로그램 시작때 이미 )
2)전역변수는프로그램시작과함께할당되며, 프로그램수행동안계속자리를차지한다.
3)함수내에서쓰이는아주큰배열은지역변수로선언하는것이효과적이다. (틀렸음. 힙에 저장해야됨)
4)스택은프로그램에게배정된공간내에서할당된다.
5)힙객체의메모리는해지된후다른프로그램에게할당될수있다.
5. 다음중C 언어에서정적객체인것을모두고르시오.
(1) 전역변수 int x;
(2) char* affil = “Computer Science Dept, KyonggiUniversity“;
(3) #define A 100
(4) 지역변수const int b = x;
(5) 지역변수static int a = 0
프로그램에서 다음 사항들이 결정되는 시점을 쓰시오.
(1) 언어 정의시간 (2) 언어구현시간 (3) 번역시간 (4) 실행시간
데이터의 기본타입
언어 정의 시간
정수의 자릿수 (데이터 크기)
c언어: 언어 구현 시간, java: 언어 정의 시간
지역변수의 할당 순서
번역 시간
동적 할당된 객체의 주소
실행 시간
함수가 언제 호출될지
실행 시간
프로그램 구조
컴파일 시간 상수
컴파일 시간에 결정됨 (#define 포함)
- java의 경우 빌트인 함수나 연산을 이용한 수식은 가능함, 즉 간단한 연산이나 함수호출계산은 자동으로 계산하여 컴파일 시 저장해준다.
* const int MAX = 100; // C
* final int MaxSize = 100; // Java
* final double MinVal = Math.sqrt(MaxSize); //JaVA
실현 시간 상수
실행 중 처음 결정되어 바뀌지 않음 (scanner로 처음 입력을 받은 뒤 변하지 않는 등)
정적 객체
정적 영역에 있는 개체(값이 바뀌지 않음을 의미하지 않는다)
프로그램 종료 전까지 할당된 주소가 변하지 않는 객체
컴파일 상수의 경우, 메모리가 할당되지 않으므로 객체가 생성되지 않는다 그러므로 정적 객체x
static은 호출한 시점에 메모리 할당이 되고 프로그램 종료시 할당 해제
댕글링 포인터
할당이 해제된 곳을 가리키고 있는 포인터
북키핑
프레임(스택 프레임)을 설정해주는것을 북키핑이라고도 함
힙
속도와 공간의 균형, 공간 문제
내부 단편화 (Internal fragmentation)
사용하는 공간보다 과도하게 큰 공간 할당시 나머지 공간이 낭비된다
예) 4mb의 데이터를 저장하는데 16mb의 메모리를 할당해 줌
외부 단편화 (External fragmentation)
남아있는 공간이 단편화되어 충분한 공간에 할당을 못하게 된다
예) 할당과 해제를 반복하면서 힙 공간이 조각난 디스크처럼 변해서 4mb를 할당할 수 있는 공간이 남아있어도 단편화 때문에 할당을 못해줌.
자유블럭(free block) 리스트
현재 쓰이지 않는 힙 블록의 링크 리스트
처음에는 전체 힙이 하나의 블록으로 존재
각 할당 요청에 대해 리스트를 검색하여 적당한 블록을 찾음
우선 할당
우선순위 이용
최적 할당
남는 부분이 제일 적은 블록을 찾음
검색 시간
자유 블록의 개수에 선형 비례함
크기 별로 자유 블록 리스트를 별도로 유지함
동적 풀을 관리
- 크기 별로 유지하는 방법
- 버디 시스템 : 크기가 2의 제곱인 블록으로 유지, 할당될 때 해당 크기가 없으면 바로 위 크기를 반으로 쪼갬, 해지될 때 가능하다면 합쳐서 큰 블록으로 유지
- 피보나치 힙 : 피보나치 수를 사용함, 약간 더 복잡하지만 내부 단편화가 약간 적음
모듈 - 정보 은닉, 캡슐화
모듈 지원 언어
- Package: Ada, Java, Perl
- Namespace: C++, C#, PHP
- 분리 컴파일: C (유사 모듈)
- Python, Ruby … import: 다른 모듈을 불러오는것 export: 이름을 모듈 밖으로 내보내는것 (다른 모듈이 참조할 수 있도록)
java: import와 export가 둘 다 명시적으로 필요 c: import만 필요
닫힌 범위
외부 이름을 참조하려면 명시적으로 import해야 됨
개방 범위
import하지 않아도 됨
별칭, 포인터, 레퍼런스 변수를 포함한 모든 다른 이름
int a int * b = &a; int &c = a;
b와 c는 별칭
오버로딩: enum(이름 오버로딩), 매개변수가 다른 여러개의 메소드(함수)들
오버로딩이 컴파일러가자동으로필요한타입에대해추가버전을생성하게 할 때 오버로딩은그런의미에서“애드혹” 다형성이라고도함
자동 형전환, c와 java 차이점
다형성
디폴트 매개변수 = c++허용 c와 java 비허용
빌트인 연산자의 재정의
허용되는언어: Ada, C++, C#, Fortran 90
사용방식(C++)
- 전위형태로정의: T& T::operator+(T& a);
- 중위형태로사용: a + b; // syntactic sugar
분리 컴파일(separate compilation)
필요성: 프로그램은점진적으로구축되고테스트되어야함
매우큰규모프로그램의전체컴파일은시간이오래걸림
모듈이일반적으로분리컴파일단위(separate compilation unit)
C와C++언어는왜파일헤더를가지는가?
파일이부분적인모듈기능을제공
이름은사용되기전에선언되어야
#include방식
파일을컴파일단위로사용하며, 각파일은명시적인헤더파일이필요
Java와C# 컴파일러가헤더정보를자동으로클래스정의로부터분석하여 추출하기 때문에 두 언어는 클래스헤더파일이따로필요하지않음
선언 전 사용의 문제
int c = 0;
void main(){
scanf("%d", &c); // 49 입력
while (c < 50){
int a = c;
int c = 55;
printf("a=%d\n", a);
c = c+1;
}
}
//결과: 무한 49 출력
코드 상의 스택과 힙, 정적 영역
프레임에 저장되는 정보들
지역 변수 이외에도 컴파일러는 서브루틴에 관련된 여러 가지 다른 정보들도 저장한다. 예를 들면 다음과 같은 것들이 있다.
매개변수와 반환값. 현재 컴파일러는 이런 값을 가능하면 레지스터에 저장하기도 하지만 가끔은 메모리의 공간을 필요로 한다.
임시공간. 이것은 보통 복잡한 계산에서 생성된 중간값들이다. 좋은 컴파일러라면 이것들도 가능한 경우 레지스터에 저장할 것이다.
북키핑 정보. 이것은 서브루틴의 반환 주소, 호출자의 스택 프레임에 대한 참조(동적 링크라고도 함), 추가로 저장된 레지스터, 디버깅 정보, 그리고 여러 가지 다른 값들이 여기에 포함된다. 이에 대해서는 나중에 더 자세히 살펴볼 것이다.
check your understanding #1
1.기계어와어셈블리어의차이점은무엇인가?
2.고급언어가어셈블리어보다어떤점에서나은가?
3.프로그램을어셈블리어로짜는것이필요한경우는언제일까?
4.왜그렇게많은프로그래밍언어들이있는것인가?
5.프로그래밍언어가성공하는요인은어떤것이있는가?
6.폰뉴만, 함수형, 객체지향언어를세가지씩나열하시오.
7.스크립트언어를세가지나열하시오.
8.언어가성공하는데보급과지원기관의역할이중요했던예를세가지설명하시오.
9.최초의고급프로그래밍언어는무엇인가? 최초의함수형언어와논리언어는?
10.최근에모바일환경에특화된언어로개발된언어사례는무엇인가? 안드로이드환경과iOS환경에대해개발된언어의이름을쓰시오.
- 해석과컴파일의차이를설명하시오. 두방식의장단점은무엇인가?
13.자바언어는어떻게컴파일또는해석되는지설명하시오.
14.컴파일러와전처리기의차이점은무엇인가?
15.초기AT&T C++ 컴파일러에서사용된중간형태는무엇인가?
16.P-code는무엇인가?
17.첫실행(Bootstrapping)이란무엇인가?
18.적시(JIT) 컴파일러란무엇인가?
19.고급언어프로그램을(네이티브) 실행코드로번역하는컴파일러의본래형태와다른예외적인컴파일러의예를세가지드시오.
20.프로그래밍환경에서컴파일러의일을도와주는링커와로더의역할을설명하시오
21.컴파일의주요단계를나열하고각단계에서수행되는작업을설명하시오.
22.어휘분석기에서파서로, 파서에서의미분석기로, 의미분석기에서중간코드생성기로전달되는자료구조는무엇인가?
23.컴파일러의전단부와후단부를구별하는경계는무엇인가?
24.컴파일에서단계와패스의차이는무엇인가? 컴파일러가다중패스를해야하는경우는어떤상황인가?
25.컴파일러의심볼테이블은어떤목적을가지는가?
26.정적및동적의미(오류)는무엇인가? 각오류의종류를나열하시오.
27.최근기종에서컴파일러로생성된코드가어셈블리프로그래머에의해작성된코드보다우수한이유는무엇인가?
28.코드생성전단계의코드개선방법세가지를나열하시오.
29.코드개선에서load 명령문을줄이는것이중요한이유는무엇인가? 어떤경우에load 명령문을없앨수있는가?
check your understanding #2
1.바인딩시점(binding time)이란무엇인가?
2.바인딩결정사항중정적으로결정되는것과동적으로결정되는것의차이를설명하시오.
3.바인딩을일찍하는것의장점은무엇인가? 또바인딩을지연시키는것의장점은무엇인가?
- 이름-객체바인딩의범위는무엇을의미하는가?
13.정적및동적범위방식의차이를설명하시오.
14.가장가까운중첩범위규칙을설명하시오.
15.범위해결연산자(scope resolution operator)는왜필요한가?
16.C와자바의이름의바인딩범위규칙을설명하시오.두언어의차이는무엇인가??
17.전방참조(forward reference)는무엇인가? 여러언어에서전방참조를허용하지않는이유는무엇인가?
18.선언과정의의차이를설명하시오. 왜이것을구분하는것이필요한가?
-
C++ 언어에서 클래스 헤더 파일이 필요한 이유는 무엇인가? 그것이 자바에서는 필요하지 않은 이유는 무엇인가?
-
정보 은닉의 중요성을 설명하라.
-
불투명한 export란 무엇인가? C와자바의exprt와import에대응하는기능은무엇인가?
-
모듈의 헤더와 몸체부를 분리하는 것은 왜 유용할까?
-
범위가 닫혀있다는 것은 무슨 뜻일까?
-
동적 범위에서 실행 시간 타입 검사가 필요한 이유는 무엇인가? 정보은닉의중요성을설명하시오.
30.별칭은무엇인가? 별칭은언어설계와구현에서어떤어려움을일으키는가?
31.C99 표준에서restrict 제한자가하는역할을설명하시오.
오버로딩, 형전환,다형성의차이를설명하시오.
31.연산자오버로딩은무엇인가? C++ 언어의일반적인함수오버로딩과어떻게다른가?
32.매개변수다형성과서브타입다형성을정의하시오. 제너릭은어떤것에가까운가?
33.오버로딩이특수한경우의(ad hoc)다형성이라고불려지는이유는무엇일까?
기타문제
각각에 해당하는 바인딩 시점을 보기에서 고르시오.
<보기> (A) 언어설계 (B) 언어구현 (C) 컴파일 (D) 링크 (E) 로드 (F) 실행 (a) 지역변수의 오프셋 (b) 다른 파일에서 선언된 전역변수의 주소 (c) 오버플로우가 일어났을 때 처리 방법 (d) 복합 타입의 종류와 만드는 방법 (e) 함수 호출 순서 (f) 전역변수의 실제주소(PA) 보기>