
C Compiler
03 Jan 2019 | C포스팅
C 프로그래밍
프로그래밍이란 목적에 맞는 알고리즘으로부터 프로그래밍 언어를 사용하여 구체적인 프로그램을 작성하는 과정을 의미합니다. 이렇게 작성된 프로그램은 먼저 실행 파일(executable file)로 변환되어야 실행할 수 있습니다.
<실행파일 생성>
1. 소스 파일(Source file)의 작성
프로그래밍에서 가장 먼저 해야 할 작업은 프로그램을 작성하는 것 입니다. C언어를 문법에 맞게 논리적으로 작성된 프로그램을 원시 파일 또는 소스파일이라고 합니다. C언어를 통해 작성된 소프파일의 확장자는 .c가 됩니다.2. 선행처리기(Preprocessor)에 의한 선행 처리
선행처리란 소스 파일 중에서도 선행처리 문자(#)로 시작하는 선행처리 지시문의 처리 작업을 의미합니다. 코드를 생성하는 것이 아닌, 컴파일하기 전 컴파일러가 작업하기 좋도록 소스를 재구성해주는 역할만을 합니다.3. 컴파일러(Compiler)에 의한 컴파일
소스 코드를 컴파일하는 이유는 대부분 사람들에게 이해하기 쉬운 형태의 고수준 언어로부터 실행가능한 기계어 프로그램을 만들기 위해서이다. 좁은 의미의 컴파일러는 주로 고수준 언어로 쓰인 소스 코드를 저수준 언어로 번역하는 프로그램을 가리킨다. 컴퓨터는 0과 1로 이루어진 이진수로 작성된 기계어만을 이해할 수 있습니다. 소스 파일은 개발자에 의한 C언어로 작성되므로, 컴퓨터는 그것을 바로 이해할 수 없습니다. 따라서 소스 파일을 컴퓨터가 알아볼 수 있는 기계어로 변환시켜야 하는데, 그 작업을 컴파일(Compile)이라고 합니다. 주로 다른 프로그램이나 하드웨어가 처리하기에 용이한 형태로 출력되지만 사람이 읽을 수 있는 문서 파일이나 그림 파일 등으로 옮기는 경우도 있다. 컴파일은 컴파일러에 의해 수행되며, 컴파일이 끝나 기계어로 변환된 파일을 오브젝트 파일(Object file)이라고 합니다. 이러한 오브젝트 파일의 확장자는 .o나 .obj가 됩니다.4. 링커(Linker)에 의한 링크
컴파일러에 의해 생성된 오브젝트 파일은 운영체제와의 인터페이스를 담당하는 시동 코드(start-up code)를 가지고 있지 않습니다. 또한, 대부분의 C 프로그램에서 사용하는 C 표준 라이브러리 파일도 포함되어 있지 않습니다. 이때 하나 이상의 오브젝트 파일과 라이브러리 파일, 시동 코드 등을 합쳐 하나의 파일로 만드는 작업을 링크라고 합니다. 링크는 링커(linker)에 의해 수행되며, 링크가 끝나면 하나의 새로운 실행 파일이나 라이브러리 파일이 생성됩니다. 이처럼 여러 개의 소스 파일을 작성하여 최종적으로 링크를 통해 하나의실행 파일로 만드는 것을 분할 컴파일이라고 합니다.5. 실행 파일(Executable file)의 생성
소스 파일은 선행처리기, 컴파일러 그리고 링커에 의해 위와 같은 과정을 거쳐 실행 파일로 변환됩니다. 최근 사용되는 개발 툴은 대부분 위에서 소개한 선행처리기, 컴파일러, 링커를 모두 내장하고 있으므로, 소스 파일에서 한 번에 실행 파일을 생성해 줍니다. 이렇게 생성된 파일의 확장자는 .exe가 됩니다.원리
컴파일러는 옮김의 과정에서 프로그램의 뜻을 보존하여야 한다. 입력받은 프로그램의 의미를 충실히 따라야한다. -이 조건이 없다면 컴파일러를 사용하는 사용자가 컴파일러를 믿고 프로그램을 작성할 수도 없고, 잘못된 옮김을 인정한다면 컴파일러를 올바르게 하기 위한 노력을 들일 필요가 없을것이다. 실용적인 면에서, 컴파일러는 입력으로 들어온 프로그램을 어떤 면에서든지 개선해야 한다. - 소스코드를 기계어로 옮긴다면 기계가 이해할 수 없었던 언어를 기계가 이해할 수 있게 개선한 것이 된다.기능
고급언어를 직접 기계어 코드를 변환한다. 자바의 경우 바이트 코드로 변환한다. 중간단계의 코드를 생성하고 이것을 해석해서 실행한다. C/C++언어와 같은 고급언어는 직접 기계어 코드로 변환한다. 마이크로프로세서는 각각 다른 기계어 코드를 가지고 있기 때문에 같은 고급언어라도 다른 기계어 코드를 생성해야 한다. 따라서 개발자는 해당 마이크로프로세서에 맞는 컴파일러 사용해야 한다. 그러나 자바는 다양한 마이크로프로세서에서 실행되도록 하는 철학을 가지고 개발되었기 때문에 바이트 코드를 가지고 해석을 해서 실행하는 방식이다. 장점은 한번 컴파일된 바이트 코드는 다른 플랫폼에서 재컴파일없이 실행할 수 있다. 그러나 단점은 바이트 코드를 해석해서 실행할 프로그램 구조가 필요하고, 직접 기계어 코드를 실행하는 것 보다 속도에서 늦다.컴파일러의 실행 단계
<컴파일 과정>
1. 어휘 분석(lexical analyze) or 스캔(scan)
- 모듈 : 어휘 분석기(lexical analyzer) or 스캐너(scanner) - 내용 : 문자열을 의미있는 토큰(token)으로 변환 - 결과물 : 토큰(token)2. 구분 분석(syntax analyzing)
- 모듈 : 파서(parser) or 구문 분석기(syntax analyzer) - 내용 : 토큰(token)을 구조를 가진 구문트리(syntax tree)로 변환 - 결과물 : 구문 트리(syntax tree), parser 에 따라 추상 구문 트리(abstract syntax tree)를 바로 생성하기도 함 ※ 구문트리(syntax tree) 와 추상구문트리(abstract syntax tree)의 차이는, 구문트리에는 세미콜론(;)이나 괄호 등이 모두 포함된다. 하지만 추상구문트리에는 이러한 불필요한(의미가 없는) 것들이 생략된다.3. 의미 분석(semantic analysis)
- 모듈 : 의미 분석기(semantic analyzer) - 내용 : 프로그램의 의미(semantic)에 따라 필요한 정보를 유추/분석 - 결과물 : 추상 구문 트리(abstract syntax tree) / 장식구문(decoration syntax tree)4. 중간 표현의 생성(intermediate representation)
- 내용 : 좀 더 코드 생성이 편하고, 여러 종류의 언어나 기계어(CPU 종속)에 대응하기 위해서, 중간에 공통의 중간표현으로 변환5. 코드 생성(code generation)
- 모듈 : 코드 제너레이터(code generator) - 내용 : 어셈블리어나 기계가 이해하기 쉬운 명령으로 변환 - 결과물 : 어셈블리어6. 최적화(optimization)
- 내용 : 좀더 질 좋은 프로그램으로 변환7. 어셈블러
- 내용 : 기계어로 변환 - 결과물 : 기계어 위 컴파일 단계에서 구문 분석(syntax analyzing) ~ 중간표현(intermediate representation) 생성까지를 컴파일러의 프론트-엔드(front end) 라고 합니다. 나머지 과정을 백-엔드(back end)라고 합니다. 단계라는 것의 중요성과 이것이 의미 분석 단계와 코드 생성 단계 사이에 있다는 사실 정도만 인지하고 있어도 충분하다.
<실행파일 생성>
가져온곳: URL