연재 완료/C Lang 이론

C언어 이론 10. 전처리기(#include~#endif)

라이피 (Lypi) 2018. 6. 3. 03:24
반응형

내용 출처 : YES C (정보공학연구소 /생능출판사)

                  혼자 연구하는 C/C++ (SoEn.kr /와우북스)


Ⅰ. 전처리기(preprocessor)

   ① 원시코드가 컴파일되기 전에 C언어의 문법과는 독립적으로 실행시켜 매크로 문장이 있으면 정의된 문장으로 치환해주는 역할을 담당하는 것

   ② 컴파일하기 전에 코드를 변경시켜주는 역할을 수행하기에 기계어로 번역되지는 않는다.

   ③ 전처리문은 #으로 시작하고, 다른 문장과는 달리 끝에 ;를 붙이지 않는다. 

   ④ 전처리문은 한행에 하나씩 써야하고, 뒤에 주석을 제외한 다른 것이 올 수 없다. 

   ⑤ 전처리기의 종류와 기본적인 역할은 다음과 같다. (일부분이다. 다음 포스트에서 나머지를 다룰예정이다.)


종류

기능

#include

지정파일을 원시 프로그램에 포함시킨다.

#define

지정 문자열을 매크로로 정의하여 치환

#undef

지정 매크로를 취소

#if / #elif / #else / 

#ifdef / #ifndef / #endif

조건에 따라 원시프로그램의 일부분을 선택하여 분할 컴파일



Ⅱ. #include

   ① 지정된 파일의 내용을 그 위치에 기술한 것으로 처리한다.

   ② (1) #include <파일명>, (2) #include "파일명" 의 형식으로 사용한다.

   ③ 형식 (1)은 지정한 파일명을 표준 디렉토리에서 먼저 찾고 없는 경우 현재 디렉토리에서 찾는다. 주로 표준 헤더파일을 지정할 때 쓴다.
   ④ 형식 (2)는 지정한 파일을 현재 디렉토리에서 먼저 찾고 없는 경우 표준 디렉토리에서 찾는다. 주로 사용자 정의 헤더파일을 지정할 때 쓴다.
   ⑤ 존재하지 않는 파일명을 포함시키려 하면 에러로 처리된다.
   ⑥ '/'를 사용하여 경로를 지정할 수도 있으나 추천되지는 않는다. 굳이 해야한다면 현재 디렉토리에 폴더를 만들어 상대경로로 처리하는 정도가 바람직하다. 
   ⑦ vs에서는 '\'도 허용하지만 호환성을 위해서 '/'를 쓰는 것을 추천한다.
   ⑧ C언어는 대소문자를 구분하지만 윈도우 파일 시스템이 대소문자를 구분하지 않으므로 윈도우 환경에서는 파일명의 대소문자를 구분하지 않는다.
   ⑨ 이 또한 호환성을 위해서 포함하고자 하는 파일명과 일치하게 쓰는 것이 좋다.
   ⑩ #include문으로 포함시킨 파일 안에 #include문이 있으면 그 안의 파일도 당연히 포함되게 된다. (재귀적으로 처리된다고 생각하면 된다.)
   ⑪ 똑같은 파일을 여러번 포함시키면 그 안의 내용이 원시코드 안에 여러번 중복되서 포함된다. 
   ⑫ 중복하면 안되는 코드가 들어있는 내용 등을 포함시킬 때는 주의해야한다. (예를 들어 함수 선언문 같은 것)
   ⑬ #include 문을 이용하여 포함시키는 파일은 주로 헤더파일이지만 cpp파일이나 txt파일 등 텍스트 파일이면 상관없다. 
   ⑭ 텍스트 파일의 기준이 궁금해서 해봤는데 word 파일은 되는데 hwp파일은 안된다.


Ⅲ. #define

   ① 매크로 상수나 함수를 정의하기 위해 사용된다.

   ② '#define 매크로명 실제값'의 형태로 사용하면 매크로명이 적혀있는 부분을 실제값으로 단순 치환한다.

   ③ #define O 1 이라고 정의했다고 문자 상수 'O'나 문자열 상수 "O"이나 DRONE 같은 형태로 있는 곳이 치환되지는 않는다.

   ④ 매크로명을 지을 때는 식별자를 지을 때의 규칙이 적용되며, 다른 식별자 명과 중복되어서는 안된다.

   ⑤ 매크로명에는 공백이 포함될 수 없지만 실제값에는 공백이 포함될 수 있다.

   ⑥ '#define 매크로명(인수) 매크로함수'로 정의하면 매크로 함수를 정의할 수 있다. (설명한 적이 있으므로 생략)

   ⑦ 매크로 함수가 아니더라도 매크로의 값이 수식이라면 괄호로 싸줘야지 예상치 못한 오작동을 막을 수 있다.

   ⑧ 매크로의 값 안에 미리 정의한 매크로명을 사용할 수도 있다.

   ⑨ 값을 가지지 않는 매크로도 정의할 수 있다. 주로 밑에 나올 분할 컴파일에 사용된다.

   ⑩ 매크로는 소스코드 전체에 영향을 끼치므로 자주 사용되는 상수값을 지정하는데만 쓰는게 좋다.

   ⑪ 범위를 지정할 수 있는 const변수나 enum변수로도 #define문과 같은 효과를 볼 수 있음을 기억하자.

   ⑫ 매크로 상수명은 대문자로 쓰는 관습이 있다. 


Ⅳ. #undef

   ① 지정한 매크로를 해제할 때 사용한다. 

   ② 이미 정의한 매크로의 값을 바꿔야 할 때 사용한다. 

   ③ #define은 중복되면 에러가 나지만 #undef는 안나므로 

      다른 파일에서 자신이 정의한 매크로 상수를 다른 파일에서 쓰고 있을 수 있는 가능성이 있으면 #undef를 써두는 것이 좋다.

   !! (vs 2017 기준으로 #define의 중복이 경고 1레벨로 내려가고, 새롭게 정의된 것으로 사용되도록 바뀐듯 하다. 물론 호환성을 위해 위의 방법을 쓰는 것이 좋다.)


Ⅴ. #if, #elif, #else, #endif

   ① if, else if, else 같은 조건을 지정하는 전처리문으로 조건에 맞는 경우에만 그 부분을 컴파일한다.

   ② if문에서는 괄호로 범위를 지정하지만 전처리문에는 괄호가 적용되지 않으므로 #endif로 범위가 끝났음을 나타낸다.

   ③ 조건식의 사용 또한 if문과 거의 동일하므로 다른 점만 정리한다.

   ④ #if문에서는 조건식에 괄호를 적지 않아도 된다. 하지만 쓰는 쪽이 권장된다.

   ⑤ 비교식에서 비교 대상에 실수값이나 문자열값은 쓸 수 없다. 조건부 컴파일의 비교식의 숫자는 표식에 가까우므로 큰 의미도 없다.

   ⑥ 나머지 연산이나 비트 연산등은 가능하나 ++, --, 포인터 연산, sizeof, 캐스트 연산 등은 쓸 수 없다. 

       매크로는 상수이므로 좌변값이 아니고, sizeof나 포인터 연산 등은 컴파일시에 평가되기 때문이다.

   ⑦ defined 연산자로 매크로의 존재 여부도 확인할 수 있다. (#if defined MACRO는 밑에 나올 #ifdef MACRO랑 완전히 동일하다.) 

   ⑧ #ifdef는 다른 조건과 사용할 수 없으니 다른 조건과 함께 비교할 때는 위의 방법을 써야한다.  

   ⑨ defined 연산자는 전처리문 구문에서만 사용할 수 있다.

   ⑩ if문이 중첩이 가능하듯이 #if문도 중첩해서 사용할 수 있다. 이때, 닫는 괄호에 해당하는 #endif을 #if문 숫자에 맞춰서 써주는 것을 잊으면 안된다.

   ⑪ if문에 대해서는 들여쓰기를 하지만 #if는 중첩되도 들여쓰기를 하지 않는게 관례이다.

   ⑫ #if문의 활용 예는 어떤 문제에 대한 해결책이 3가지가 있고 각각의 성능을 테스트 해보고 싶을 때 사용하면 코드를 수정하지 않고 매크로 조건문만 바꿔보면 된다.

   ⑬ 고객이 원하는 방법이 각각 다르다면 그에 맞춰서 컴파일해주기도 이렇게 하는게 편하다.

   ⑭ #if 0 은 언제나 거짓이므로 매우 긴 구간을 주석 처리할 때 사용할 수 있다. /* */는 중첩이 안 된다는 문제가 있지만 #if 0은 중첩이 가능하다는 장점도 있다.


Ⅵ. #ifdef,  #ifndef

   ① 매크로가 정의되어 있는지를 확인하고 정의되어 있을때나 정의되어 있지 않을때만 그 부분을 컴파일하는 전처리문이다. #endif가 닫는 괄호 역할을 한다.

   ② 매크로가 정의되어 있는 경우는 #ifdef macro 로, 정의되어 있지 않은 경우는 #ifndef macro로 구분한다.

   ③ 똑같은 프로그램의 일반 버전과 프로 버전이 있고 프로버전에만 새로운 기능을 추가해주려 하는 경우 #define pro를 선언하고 

       프로버전에만 들어갈 기능은 #ifdef pro로 묶어두면 일반 버전을 컴파일 할 때는 #define pro를 빼면 일반 버전용이

       프로버전을 컴파일할 때는 #define pro를 넣어주면 프로버전용이 만들어진다.

   ④ 만약 여기에서 일반버전에만 기능을 추가해주고 싶다면 그 부분을 #ifndef pro로 묶어주면 된다.

   

   

반응형