일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 프론트엔드
- 자료구조
- 컨테이너
- 릿코드
- 웹팩
- GraphQL
- alexnet
- 타입스크립트
- APOLLO
- C
- 알고리즘
- 자바스크립트
- cors
- Machine Learning
- 프로세스
- pytorch
- 포인터
- RT scheduling
- 브라우저
- 연결 리스트
- 배열
- 프로그래머스
- 해시테이블
- 이진탐색
- 스택
- 연결리스트
- 큐
- 코딩테스트
- RxJS
- vue3
- Today
- Total
프린세스 다이어리
[C/C++] GCC가 무엇인가요? GCC의 컴파일 과정 4단계 본문
C 개발환경 세팅하다가 GCC, G++이 무엇인지조차 모르면서 세팅하는 게 답답해서 정리해보았다. 먼저 GCC에 대한 글이다.
1. GCC의 뜻, 역할
GCC는 본래 C언어용 컴파일러로 시작하여, GNU C Compiler의 약자였으나, 2.9 버전에 이르러 C언어뿐 아니라 오브젝티브 C(Objective C), 파스칼, 에이다 등과 같은 언어를 지원하게 되면서 GNU Compiler Collection으로 이름이 변경되었다. Linux, 윈도우 등 수많은 운영체제를 지원 가능하여 높은 호환성을 가지고 있고, 자동 레지스터 할당, 반복적인 코드 제거, 상수 곱셈 최적화 등 많은 최적화를 수행하는 컴파일러다. 또 GCC는 IDE를 가지고 있지 않은 command line 컴파일러다.
C 파일을 GCC로 컴파일하는 과정을 그림으로 나타내면 다음과 같다.
2. GCC의 컴파일 4단계 알아보기
GCC가 컴파일하는 과정을 살펴보기 위해 간단한 .c 파일을 만들었다.
2-1. 전처리기 실행
#include, #define, typedef, extern 과 같은 구문을 처리하는 단계. 방대한 양의 소스코드가 정의한 코드 위에 붙는 걸 확인할 수 있다. 즉, main.c의 stdio.h 속에 있는 모든 코드들이 main.i에서는 main함수 위에 등록된다고 보면 된다.
명령어로 바로 확인해보았다.
$ gcc -E main.c -o main.i
전처리기 실행을 완료한 main.i 코드에서는...
쭉쭉 내려가다 보면
내가 main.c 파일에서 정의한 main 함수는 main.i 파일에서 무려 540번째 줄에서야 등장하는 것을 확인할 수 있었다!
2-2. 컴파일러 실행
컴파일러는 고수준언어를 저수준언어로 나타내는 역할을 수행한다. 여기서는 전처리된 파일을 어셈블리어로 바꿔주는 역할을 한다. 전처리기 실행 단계와는 달리, 컴파일 단계에서는 어셈블리어로 만드는 과정에서 실제로 호출되고 사용되는 부분만 번역하기 때문에 전처리기 완료된 파일인 test.i보다 줄 수가 짧다.
바로 확인 간다.
$ gcc -S main.i -o main.s
전처리를 거친 main.s 함수는 이렇게 변했다.
main.s 파일명 옆에 어셈블리어를 의미하는 듯한 ASM이라는 로고가 붙어 있다! 역시 전처리기를 거친 main.i 파일보다 훨씬 짧게 30줄밖에 되지 않는다. 벌써 너무 로우 레벨이라 나는 잘 모르겠고 하단에 "hellowwwww mainc\n"라고 printf 함수를 실행해보려고 쓴 코드밖에 눈에 띄지는 않는다.
2-3. 어셈블러 실행
어셈블리어 코드를 기계어로 바꿔주는 역할을 한다. 이렇게 변환된 코드는 리눅스는 test.o, 윈도우는 test.obj 확장자를 사용하며, 오브젝트 코드라고 한다. 이 기계어는 프로그래머가 볼 수 없고, 디스어셈블로 기계어를 다시 어셈블리어로 되돌린다면 내용을 확인할 수 있다.
어셈블리어로 어떻게 변환되는지 확인해보았다.
$ gcc -c main.s -o main.o
이상한 문자가 나온다. 프로그래머가 읽을 수 없다길래 이해하지 못한다는 의미인 줄 알았더니, 진짜 읽을 수가 없었다.
hexdump를 이용하면, 텍스트 또는 바이너리 파일의 내용을 16진수로 출력할 수 있다고 하여 출력해보았다.
$ hexdump main.o
이쯤 보면 될 것 같다.
2-4. 링커 실행
만들어진 오브젝트 코드 파일을 하나로 묶어 실행파일로 만드는 과정이다. 일반적으로 컴퓨터에 소프트웨어를 설치할 때 자주 보던 .exe파일 형식으로 합쳐지는 것이다.
실행 파일을 만들어보았다.
$ gcc main.o -o main.exe
실행을 시키면
잘 나온다.
이상으로 GCC의 컴파일 4단계를 알아보았다.
참고한 블로그
https://hwan-shell.tistory.com/185
https://onecellboy.tistory.com/146
'C, C++' 카테고리의 다른 글
[C] 포인터 개념, 활용방법 정리 (0) | 2021.09.26 |
---|---|
[C] 배열 선언방법, 문자열 정리 (0) | 2021.09.25 |
[C] 함수 문법 정리 (0) | 2021.09.25 |
[C] 반복문 문법 정리 (0) | 2021.09.24 |
[C/C++] system("pause") 커맨드를 사용하면서 만난 에러와 새로 알게 된 것 정리 (0) | 2021.09.22 |