본문 바로가기

Developement

[C/C++] precompile, 프리컴파일에 대해 ...

오랜만에 쓰는 강의 아닌 글이 입니다.
요즘 C 언어 한다고 자신감에 좀 쩔어 있는 몇몇 개발자들 보고 있으니, 프리컴파일이나 링크에 대핸 사전적인 지식은 전무 하더군요. (마소의 비주얼 스튜디오 덕분에 디버깅도 비주얼 스튜디오 없으면 할 줄 모릅니다 ... )

윈도우는 리눅스나 유닉스 기반과 달리, OS 가 설치되면 컴파일러는 사용자가 알아서 설치 해야 합니다.
사실 일반 사용자가 컴파일러를 쓰는게 이상한 일일 수도 있겠습니다만 ..
적어도 개발 한다는 친구들은 이 컴파일러에 대해 좀 알아야 하지 않을까요 ?

어셈블리어 까지는 몰라도 내가 만든 코드가 어떻게 컴파일러에서 Object 로 바뀌는지는 좀 알았으면 하는 마음에 글을 한자 써 봅니다.

먼저 아래 이미지 처럼 .. hello world 틱한 코드 몇줄 씁니다. 
 


이 코드는 무작위 적인 상수를 피하기 위해서는 좀 해 줘야 할 #define 사용을 한 예 입니다.
제대로 하려면 #define 은 모두 header 를 만들어 한곳에 몰아 주는 버릇을 가지는 것도 좋습니다.

일단, 위 코드를 보면 당연히 코드 내에 #define 에 지정된 값들이 들어 가겠죠?
그런데 실제 컴파일러에서는 이 코드를 어떻게 볼까요 ?

자신의 PC 에 gcc 가 설치 되어 있다면 아래와 같이 해 봅시다.
 


gcc -E [프리컴파일 할 C/C++ 파일]


참 쉽죠?
이러면 해당 C 파일이 프리컴파일 되어 화면에 뿌려 집니다.
이걸 파일로 보고 싶다면 direction 을 사용합니다.

예)
gcc -E precom1.c > precom1.txt


참 쉽죠?
근데 이 direction 이 뭔지도 모르는 친구들이 너무 많아서 속이 좀 답답 합니다...

이러면 아래의 내용들이 precom1.txt 에 들어가 있습니다.


물론 위 내용은 화면상에 아무것도 안 나오겠지요.
그리고 만들어진 내용을 보면 놀랍게도 코드 위에 넣은 #include <stdio.h> 내용이 들어가 있게 됩니다!
그리고 #define 으로 정해 진 값들이 이미 코드에 대입되어 있는걸 알수 있습니다.

여기서 코드에 직접 1과 10을 쓰는 것과 #define 으로 하는 차이를 모르겠어요. 라고 하신다면 당신은 크게 반성해야 할 것 입니다.
만약 위처럼 단순한 코드가 아니라 복잡한 연산 수식을 사용하는 부분에서 무작위 적인 상수 남발이 사용 된다면?
만들땐 몰라도 프로그래밍을 하는 주체는 기계가 아닌 사람이고, 혼자 일 하는 경우가 아니라 많은 사람이 함께 만들어 가는 코드라면 상수 사용은 잠정적인 큰 범죄를 계획 하는 것과 같습니다.

예로, A 라는 프로그래머가 자신이 자랑스럽게 만든 함수들 안에 상수를 남발 하였고, 이 함수가 여러개의 c/c++ 파일에서 남용 되었다고 칩시다.
그리고 이 A라는 양반은 일을 그만두거나, 다른 이유로 자신이 만든 코드를 유지보수 할수 없게 되고, D 라는 친구가 이전에 A 가 만든 코드의 수식을 수정해야 할 일이 생겼습니다.
그리고 D 는 A 의 코드를 수정하기 위해 함수들을 보는 순간 좌절하게 될 겁니다.
동일하게 사용하는 여러 같은 수들이 모두 코드에 상수로 지정되어 있었기 때문 입니다.
D 도 사람인지라 나름 열심히 찾아 해당 상수를 수정 합니다만, 막상 컴파일과 링크를 거져 나온 결과물에 뭔가 이상을 발견 합니다.
D 가 작업한 값들이 A 가 만든 코드에서 수정한다고 수정한 것에 빠진 부분들을 있었기 때문 입니다.

만약 A 가 이런 상수를 #define 으로 만들어 한곳에 정리 해 두었더라면?
D 는 #define으로 지정된 이름을 보고 다음 여러가지 이점을 가질 수 있었을 겁니다.

 - 정의 된 수가 대충 무슨 역활을 하는 것 인지 알 수 있다.  
 - 한군데만 값을 수정 하면 참조 되는 모든 코드에 적용이 된다.
 - 위의 이유로 작업이 용이해 지고, 디버깅 시간도 줄이고, 작업시간도 줄인다.


많은 이점들이 있지요.
그래서 상수의 사용을 줄이는 것이 중요하고, 이는 미래를 위한 투자가 되는 것 입니다.

그리고 이쯤 좀 똑똑한 친구들은 이걸 기억 할 겁니다.
헤더파일에 들어 가 있는 문구들 .

#pragma once


- 또는 -
 
#ifndef __INCLUDE_1__
#define __INCLUDE_1__  ...


#pragma 는 컴파일러에 의존하는 부분이 강해서 gcc 3.xx 버젼대에서는 무시되어 버리기 때문에 VC++ 에서만 사용이 가능한 부분입니다만, 둘다 같은 역활을 하기 위해서 사용합니다.
다만, #pragma once 는 #ifndef .. 와 달리 인식 되는 컴파일러는 헤더를 한번만 컴파일 하고, #ifndef - 로 지정된 경우는 참조되는 c/c++ 파일이 컴파일 될 때 마다 참조하여 효율이 떨어지는 차이가 있습니다만, 둘다 동일한 역활을 합니다.

위 문구들은 모두 중복된 헤더 사용과, symbolic link 오류 를 피하기 위해서 입니다.

이걸 왜 하는지 모르겠다는 사람들을 위해 다음에 더 글을 쓰겠지만, 헤더에 위와 같은 중복된 참조를 피하기 위한 노력되 상수를 피하고 precompile 을 이해 하지 않고서는 그 진정한 의미를 알수 없다는 겁니다.

이는 개인적인 불만으로 쓰인 글 이긴 합니다만 ...
프로그래밍을 하는 입장에서는 이런 상수를 쓰는 것을 줄이고, 더 많은 이해를 함 으로서 자신의 값어치를 올리는 자세를 가졌으면 좋겠습니다.