[C언어] #define 와 #undef

COM2008. 4. 5. 13:33 |
#define 은 무념무상으로다가 바꿔치기 해주는 역할을 하는데, 이거슨 preprocess(전처리) 과정에서 이루어지므로, 사실상 코드에 직접적으로 손을 대는 것과 같다.

소스를 통해 전반적으로 반복되는 상수나 혹은 수식 따위가 있을때 그것을 다른 식별자로 치환시켜 놓고, 프로그래밍하면, 이후에 그 상수나 수식따위의 변경이 필요할때, #define 에서 한번만 수정해주면, 코드 전체를 통해 일괄적으로 수정한 효과를 보게 되며, 이는, 프로그램의 이식성을 높여준다.

즉, #define 은 매크로정의 전처리기이다.


사용법은 보통 다음과 같은 형태를 갖는다.

#define identifier token_stringopt
#define identifier(identifier, ... , identifier) token_stringopt
                     //파라메터를 갖는 매크로

보다시피 토큰-스트링이 옵션이기 때문에 없어도 된다. 경우에 따라 그것이 정의되었는지 여부만을 따질 때가 있기때문이다.

토큰스트링이 있을 경우, 전처리 과정에서, 명시된 식별자와 이후의 토큰스트링을 같다고 정의한다.
정의가 길어져서 행이 넘어갈땐 backslash 를 사용하여 연장할 수 있다. 매크로정의는 컴파일전에 우선적으로 코드를 치환시킨다.

----------------------------------------------------------------------------------------------------

#define 은 파라메터를 사용하여, 수식따위를 치환해서 쓸때도 유용한데, 이때 주의할것은 전처리기가 무념무상으로 치환하기 때문에, 괄호()를 사용하는 것이 예기치 못한 오류를 막는 좋은 습관이되겠다.

예를들면,    #define sqr(x) x*x         보다는  #define sqr(x) (x)*(x)      로 쓰는것이 좋다.

왜냐면, sqr(a+b) 로 쓸때, 우리가 원하느 것은 (a+b)*(a+b) 인데, 첫번째 방식으로 #define 을 쓸경우, a+b*a+b 가 되어 예상과 다른 결과를 준다.

이때, x는 int니 char 니 하는 거랑은 전혀상관없이, 그냥 컴파일 전에 소스에서 치환하는 인자일뿐이다.


위에서 보듯이, 파라메터를 사용한 매크로는 겉보기와 기능에서 함수와 같은 역할을 수행할 수 있다.
이것은 많은 경우에 매우 권장되는데, 기능은 함수와 같으면서도 제어의 흐름상 함수호출이 없기때문이다.

게다가, 세미콜론 ; 을 사용해서 디파인을 사용하면, 하나의 모듈로서도 써먹을수가 있다.

----------------------------------------------------------------------------------------------------

또한, #define 은 코딩의 구문을 자신의 기호에 맞게 변경하는데도 쓸 수 있다.

예.  #define NOT !=


주의.  #define A B 의 형식에서, A를 B로 대체하는데, 이때, A는 identifier 혹은 그것에 파라메터가 달린 꼴 이므로, identifier 를 만드는 규칙에 따라야 한다. 가령 !나 # 따위의 기호는 사용할 수 없다. 반면 B위치에 들어가는 것은 token_string 이므로, ! 나 = 따위의 연산자나 ; 따위의 펑츄에이션도 가능하다.



#define 은 앞에서 정의된 매크로를 재사용하여 정의할수도 있다.

예.

#define min(x,y) (((x)<(y))?(x):(y))
#define minmin(a,b,c,d) min(min(a,b),min(c,d))


-------------------------------------------------------------------------------------------------


매크로 정의를 해제하는 방법은 #undef 를 쓰면 된다.

#undef identifier

아니, #undef 는 왜 쓸까? 애초에 #define을 안하면 될 것 아닌가... 하지만 그렇지가 않다. 우리가 #include 하는 헤더파일에 대해 모든것을 알고있지 않는한 #undef 는 필요하다. 내가 정의하고픈 매크로가 포함하려는 어떠한 헤더파일에 이미 정의되어 있을 수 있기 때문이다. 표준헤더가 아닌 사용자정의 헤더의 경우에는 특히 더 그렇다.

인자를 갖는 매크로를 해제할때도, 식별자만 써주면 된다.

다음과 같은 형태로 많이 쓴다.

#undef identifier
#define identifier