[c++] 여러 파일을 컴파일하자.

여러 파일을 컴파일하는 부분은 c나 c++를 사용하는 개발자에게 기본이다. 그래서 조사하고 공부해보기로 하였다.

1. 코드는 function들로 구성되어 있다. 컴파일러가 function을 어떻게 처리할까? c/c++ 코드를 작성할때 우리는 function을 선언하고 / 정의하며 / 호출한다. 정의하고 호출하는 파일은 같을 수 있고, 다를수도 있다. (ref : https://www.tutorialspoint.com/cprogramming/c_functions.htm)

  • function declaration은 compiler에게 함수의 name, return type, parameter type을 알려준다. (parameter name은 중요하지 않음. )
  • 이러한 declaration은  함수가 정의된 파일 외의 다른 파일에서 호출할때 필요하다. 너는 함수 호출하는 파일의 윗부분에서 선언을 해줘야 한다. (**즉, 함수를 정의한 파일은 윗부분에 선언할 필요가 없다.)
2. 컴파일러의 역할을 다시 한번 보고 넘어가자. (ref : http://courses.cms.caltech.edu/cs11/material/c/mike/misc/compiling_c.html)


  • 우리가 작성하는 코드는 source code file(.c / .cpp) 또는 header file(.h)이다. 
  • source file은 function definition을 가진다.
  • header file은 function declaration 및 preprocessor statement를 가진다. (#define 과 같은..) 헤더 파일의 주요 목적은 source file이 외부에 정의된 함수를 호출할 수 있도록 연결하는 것이다.
엄밀하게 컴파일러는 c파일을 assembly 파일로 바꾸는 걸 의미하지만, 포괄적 의미로 c를 object file(기계어)로 바꾸는 걸 의미할 때도 있다. 여기선 후자로 설명한다.
  • preprocessor : 컴파일러가 컴파일하기 전에,  preprocessor은 source file을 한번 변환한다. 이 변환된 파일을 일종의 expanded / modified source file이라 할 수 있다. 이 modified source file은 영구적으로 디스크에 저장될수도, (컴파일 전까지만 )메모리에 임시로 저장될 수도 있다. 
  • preprocessor 명령어는 '#'으로 시작한다. (#define / #include )
다음으로 컴파일러가 object file을 생성한다. 
  • 컴파일러는 각 file 단위로 object file을 생성한다. 자, 여기가 바로 header file이 존재하는 이유이다. header file을 통해 외부 정의된 함수들을 구별해서, 선언해줘야 해당 파일은 object file로 안심하고 변환할 수 있는 것이다.
  • gcc -c foo.c 를 치면 object file까지 생성된다. 
다음으로 각 object file을 linker가 결합하여 실행파일(binary executable)을 만든다.
  • 이 과정은 사용자가 compile한 object file 뿐 아니라, precompile 된 각종 library file도 결합하는 과정이다. 
  • 이러한 library file은 .a / .so로 끝난다. -> 이부분은 추후 제대로 정리하겠다.
  • gcc foo.o bar.o baz.o -o myprog 를 하면 링커가 3개의 object file + library file을 linking하여 myprog이라는 binary executable을 생성한다. 
  • gcc -Wall -c foo.c -> -Wall은 의심스러운 코드부도 디버깅시켜, 빠르게 에러를 알아차릴 수 있또록 한다.
참고로 gcc 옵션을 살펴보자
  • gcc -E foo.c : 전처리만 진행(foo.E)
  • gcc -S foo.c : 어셈블리파일(foo.i)까지 생성
  • gcc -c foo.c : 오브젝트파일(foo.o)까지 생성
  • gcc -W : 모든 에러 메세지 출력
  • gcc -o : 출력 파일명 지정
  • gcc -I : 추가 헤더파일이 있는 디렉토리를 지정
  • gcc -L : 추가 라이브러리 디렉토리를 지정 (디렉토리만 지정하는지, 아니면 디렉토리 모든 파일을 링킹하는지 모르겠음! )
3. 이를 통해 정리해보자면, 컴파일러는 각 파일별로 컴파일하며, 나중에 링킹한다. 따라서, 호출된 함수가 다른 파일에 정의되어있을 수 있다. 이를 관리하기 위해 함수를 call하는 파일은 위에 함수를 선언해야한다. 이를 #include를 통해 매우 깔끔하게 관리할 수 있는 것이다. 


4. 이 시점에서 알아야할 개념이 static과 extern이다. 각 속성은 변수, 함수를 외부 파일에 공개할지, 내부 파일에서만 사용할지 여부를 결정한다.

  • extern + 함수 / 변수 : 해당 함수 / 변수를 외부 파일로부터 받아와 사용한다는 의미이다. 기본적으로 함수는 default상태가 extern이기 때문에, extern을 붙이지 않아도 외부 파일로부터 호출할 수 있다. 
  • extern+ 변수의 경우 extern을 붙여야 다른 파일의 변수를 참조한다는 의미가 된다. 따라서 extern a=3;과 같이 바로 초기화시킬 수 없으며, 선언만 해줄 수 있다.
  • static + 함수 / 변수 : static으로 함수 / 변수를 선언 및 정의하면, 해당 파일에서만 함수 / 변수를 사용하겠다는 의미이다. 
    • extern + 변수 : 다른 파일의 변수를 참조함
    • (default)변수 : 변수를 다른파일에 공개함
    • static + 변수 : 해당 파일에서만 변수를 사용함
    • extern + 함수 / (default)함수 : 다른 파일의 함수를 사용함
    • static + 함수 : 해당 파일에서만 함수를 사용함.

특히, static은 보안과 밀접한 관련이 있어, 능력있는 개발자는 필히 사용하여 접근을 제어한다.















댓글

  1. Best eCOGRA Sportsbook Review & Welcome Bonus 2021 - CA
    Looking for an ford fusion titanium eCOGRA Sportsbook Bonus? At https://deccasino.com/review/merit-casino/ this eCOGRA Sportsbook review, we're bsjeon.net talking about a variety 토토 사이트 도메인 of worrione ECCOGRA sportsbook promotions.

    답글삭제

댓글 쓰기

가장 많이 본 글