안녕하세요 조신입니다.
7기 1차인 신입 카댓이라 많이 부족하겠지만 공부했던 것들을 공유하는 글로 정리한 글을 공유해보고자 합니다.
컴파일이란?
일단 많은 분들이 컴파일이란 무엇인가 궁금해 하십니다. 컴파일을 한마디로 말해서 소스코드를 컴퓨터가 이해할 수 있는 어셈블리어로 변환하는 과정입니다.
많은 분들이 그냥 gcc를 사용하시지만 실제로 저희가 사용하는 gcc는 컴파일만 해주는 것이 아니라 전처리, 컴파일, 어셈블리, 링킹까지 한번에 해서 실행파일을 만들어주는 엄청난 드라이버입니다. (c++에서는 g++입니다.)
전처리과정이 뭘까요?
#include 로 선언된 헤더파일이나 #define 으로 정의된 매크로 등을 실제 코드로 바뀌게 됩니다. 이때 전처리과정은 텍스트들이 치환만 됩니다!(연산은 일어나지 않아요...!)
헤더파일이 뭘까요?
헤더파일에는 함수의 원형, 구조체,열거형등 여러가지를 적어 놓을 수 있어요. 이 헤더파일을 보면 어떤 함수를 사용할 지 알수가 있습니다.
다양한 파일에서 include"헤더.h"를 하면 다함께 컴파일 할때 전처리 과정에서 처리가 돼고 다양한 파일에서 사용할 수 있는 것이죠!!
헤더파일은 함수의 프로토타입만 선언이 되어있어야해요..! 그 함수의 실제코드는 다른 소스파일(C파일)에 담겨있어요..!! 컴파일시 전처리과정에서 #include 자리에 함수의 프로토타입이 들어가게 됩니다. (다른 파일에서 만든 함수를 코드에서 사용하려면 함수의 원형을 적어주는 과정을 생략해준다 정도로 생각하시면 될 것 같네요)
오브젝트 파일이란
소스파일들이 전처리, 컴파일, 어셈블리(기계어로 바뀌는 과정이라고 생각하세요) 과정을 거치면 .o 확장자를 가진 object 파일들이 됩니다!!
목적파일은 소스 코드를 컴파일 한 어셈블리가 들어갑니다. 그리고 컴파일 할때는 다른 파일들을 참조하지 않기 때문에 참조파일을 지정해주지 않아도 오브젝트 파일은 생성을 할 수가 있습니다.
링킹이란 ?
이 친구들이 링킹이라는 과정을 거치면 실행파일이 되는 겁니다!!
즉 gcc가 각 object 파일들을 하나의 실행파일로 묶는 작업이 링킹입니다!
이 모든 과정을 보면 gcc main.c test1.c test2.c test3.c .....test9.c 를 입력하게 되면 하나의 a.out 만 생기는 과정입니다!! (gcc가 생각보다 한번에 많은 일을 했었죠?)
어떤 헤더파일은 <>꺽쇠로 표시하고 어떤 것은 " "로 표시하는가?
여기서 많은 분들이 궁금해 하실 수 있는 부분인데 정확하게 정리된 글이 없길래 정리를 해봅니다.
#include<헤더파일>
<> 이렇게 감싸져 있는 경우 컴파일러가 설치된 폴더에서 헤더파일을 찾으라는 지시입니다.
예를 들어 iostream(c++)이나 stdio.h(c) 같은 헤더파일은 컴파일러랑 같은 폴더에 위치해습니다. 따라서 <>로 표시해서 같은 경로에서 찾으라는 명령입니다.
#include "헤더파일"
““ 이렇게 감싸져 있는 경우 사용자의 프로젝트 폴더나 개발자가 추가로 포함해준 디렉토리로 지정해준 경로에서 찾으라는 명령입니다.
즉 개발자가 만든 헤더파일이나 추가로 외부 라이브러리를 포함하고 싶을때 위같은 명령을 사용합니다.
주의 !!예시!!
#include<stdio.h> 라고 했을 때 /usr/include/stdio.h 파일을 가져오는 것입니다.
#include "stdio.h”라고 할때는 현재 컴파일중인 디렉토리에서 가져오게 되고 따라서 “”로 사용하고 싶다면 경로를 지정해서 #include "/usr/include/stdio.h” 이렇게 해야하는게 정석이지만 저희 컴퓨터는 똑똑합니다..
<>는 컴파일러가 미리 정해놓은 위치 A에서 헤더파일을 찾지만 ""는 저희가 미리 정해놓은 위치 B에서 헤더파일을 찾습니다. 만약 찾을 수 없으면, A에서 다시 찾습니다.
이렇게 알아서 찾습니다.
마치며
makefile까지 한번에 적으려고 했는데 내용이 너무 방대해질 것 같아서 우선 헤더파일에 대한 이야기를 나눠봤습니다.
라피신 때 많은 사람들에게 공유 했던 내용을 가져와 봤는데 조금이라도 유익했다면 좋겠네요. 감사합니다.