본문 바로가기

2018-02/c++

g++ 컴파일러 실험실

기본 컴파일 ( 단일 파일 )

g++ -o (exe 파일명) myfile.cpp

>> 새로운 파일을 생성


링커 파일 생성(.o파일)

g++  -c myfile.cpp

>> 자동으로 myfile.o 파일 생성


여러 파일 컴파일

g++ -o (exe파일명) myfile.cpp main.cpp

>> 새로운 실행파일을 생성

* dependency 순서로 적어야 한다.

g++ main.cpp myfile.cpp는 main에서 myfile을 링크해야 해서 안된다.


링커 파일 잇기

g++ -c myfile.cpp

g++ -o (exe파일명) main.cpp myfile.o

* 이 경우에는 순서 상관없음


[실험실]

헤더 파일과 몸통 파일의 이름이 다르면?

>> 상관없다.

즉 myfirst.h의 내용을 mysecond.cpp에 담은 다음에

g++ -c mysecond.cpp로 해서 mysecond.o를 만들어서

g++ -o test3 main.cpp mysecond.o로 하면 mysecond.o의 내용으로 실행된다.

즉 어쨌든 컴파일은 헤더가 아닌 cpp 파일 몸통을 하는거니까, 특정 헤더의 내용은 그걸 불러오는 cpp 파일을 기준으로 링크되고 그걸 링크하는 main에서는 링크된 그 파일을 링크해다 쓰는 듯 하다.


그러면 두개의 cpp에서 헤더 함수를 동시에 구현하면?

g++ -o test4 mysecond.cpp myfirst.cpp main.cpp

를 하면 mysecond.cpp에서 func의 정의를 이미 했다!! 하면서 myfirst에서 컴파일 에러가 난다.


헤더 파일을 이중으로 부르면?

그니까 mysecond.cpp에서 myfirst.h를 부르고 main.cpp에서 mysecond.h와 myfirst.h를 부르면?

아직까지는 문제가 없었는데

#pragma once를 쓰는게 관례인것 같다.

* 요즘은 문제가 없게 설계된 듯? 문제시 자삭


헤더 파일 없이 cpp 파일만 합칠 수 있나?

>>  된다.

#include "robot2.cpp" 식으로 cpp 파일도 합칠 수 있다.

합치는 방식은 아예 인클루드 부분에 코드를 붙여버리는 방식이다.

robot2.cpp에서 적은 using namespace std와 iostream 모두 main2에서 사용가능하게 된다.

단, g++ robot2.cpp main2.cpp를 해버리면

robot2.cpp가 중복이라고 에러 뜬다.


파일 이름에 의미가 있나?

그냥 정리하기 좋을 뿐이다. robot.jinhyuk도 인클루드 된다. 근데 컴파일러는 파일 구분하니까 써줘야 한다.


using namespace std?

이거 헤더에서 쓰면 그 헤더를 인클루드 하는 모든 애들도 다 적용되 버린다.

근데 헤더 구현하는 cpp에서 쓰면 다른 cpp에는 전달이 안된다(확실).


인클루드?

다른 cpp에 있는 인클루드는 포함 안된다.

헤더의 인클루드는 인클루드 한 곳에서 모드 인클루드된다.


-I로 인클루드 주소를 추가해 주면 컴파일러가 거기도 베이스 인클루드 디렉토리로 확인해 준다.

g++ -I ~/test test.cpp main.cpp

>> OK

g++ test.cpp main.cpp

>> <test.h> 가 없어서 안됨!!

그니까 <> 를 쓸 수 있다는 차이가 있음


< 구조 이해 >

그니깐, 컴파일러는 주어지는 cpp파일을 통해 헤더를 채워서 o 파일을 만들고

이것들을 이어서 하나의 실행파일을 만든다.

아마도 내부구조는 이렇게 되지 않을까

(먼저 주어지는 cpp에서 헤더 소스를 그대로 복 붙)

그러면 그 cpp파일에서 함수 프로토 + 원형 정의된 cpp 파일이 됨.

그리고 다음 cpp 파일에서 그 헤더를 붙이면 <헤더 뿐만이 아니라 이렇게 링크된 오브젝트 파일> 이 붙게 된다.

왜 그러냐면 만약에 두개의 cpp파일로 헤더를 이중 정의하려고 하면 두번째 파일에서 <이미 붙은 오브젝트임> 으로 에러가 뜬다..!!

그러므로 헤더 >> cpp >> 링커 오브젝트 파일

오브젝트 파일을 임포트해서 함수 사용

의 과정으로 컴파일 되는 것으로 보인다.

오브젝트 파일로 만들어버리고 소스를 복붙하는게 아니다보니 두번 인클루드해도 문제가 없고 한쪽 cpp에서 사용한 인클루드와 네임스페이스가 다른쪽에 전달이 안된다.


** 좀더 특이한 사실

헤더 파일을 인클루드 안해도 링크 오브젝트 파일을 형성하는 과정에서 자동으로 다 모아서 함수 원형과 연결해주는 듯 하다.

cpp 파일이 이름이 달라도, 심지어 맞는 헤더 인클루드 안해도 그냥 함수가 붙어 버린다.

근데 헤더를 인클루드 하는 이유는 일단 헤더에 인클루드 한걸 전부 받을 수 있어 편하다.

하나의 헤더의 함수를 채우는 cpp가 여러개여도 붙는다.


근데 사용하는 메인에서는 test.h를 인클루드 해야된다.


cpp 파일 내부에서 헤더에 없는 함수를 정의하면 main에서 받아보지 못하는 로컬 함수가 되어버린다. 헤더가 매개체가 되는 것은 맞다.

---


요점 다시


cpp 파일들은 각각 함수와 클래스를 가지고 있다.

다른 cpp 파일의 함수를 사용하고 싶으면 헤더를 통해 서로 이어야 한다.

헤더를 인클루드 하면 그 헤더가 활성화되는데, 그 헤더에 맞는 cpp 내의 함수를 찾아서 붙인다.

그리고 그 오브젝트 파일을 만들어 뒀다가 다른 함수에서 헤더를 불러 함수를 쓸 수 있도록 한다.

그 헤더를 완전히 사용하려면 그 헤더의 함수들을 만드는 모든 오브젝트 파일들을 함께 컴파일 해 주어야 한다.

헤더는 그렇게 다른 cpp 파일들의 의존관계를 이어주는 역할이다.

헤더가 없으면 서로 다른 cpp 파일 내의 함수들은 서로 사용 불가능하다..!!!


헤더의 역할 : 서로 다른 cpp 파일들 사이의 다리 역할이다. 서로 다른 cpp 파일들의 함수와 변수, 클래스 등을 사용할 수 있도록 한다.


<실험>

헤더 파일에 구체적인 내용을 적는 경우에는 defined twice라고 에러 뜬다. ifndef나 pragma once 써도 그렇다. 결국 헤더 - cpp 구조로 만들어야 한다는 것.


* 최종적으로 오브젝트 파일들을 링크할 때, g++에서 main 함수를 찾아서 exe의 입구를 만들어 준다.


(추가)

-L은 라이브러리 주소를 찾아주고

-l을 붙여서 라이브러리 이름을 불러준다.

라이브러리는 .a 형태의 확장자로 보통 여러개의 오브젝트 파일을 지닌다.


-Wall  :  워닝을 보여준다.

-g : 디버거를 연결하는 기능.


'2018-02 > c++' 카테고리의 다른 글

make, premake4 실험실  (0) 2018.05.04
c++ 실험실  (0) 2018.05.04
g++ 컴파일러 실험실  (0) 2018.05.04
c++ 라이브러리와 함수 요약  (0) 2018.04.18
연산자와 비트 연산  (0) 2018.04.13
자료구조 요점정리  (0) 2018.04.02