2006년 08월 20일 Posted title : [003]#define, #if, #else, #ifdef, #ifndef, #undef, #endif
#define은 매크로 상수, 매크로 함수, 매크로 선언으로 구분이 된다.
#define SIZE 10 //매크로 상수
#define MUL(a, b) ((a)*(b)) //매크로 함수
#define _OS_WINDOW_ //매크로 선언

매크로 상수와 함수는 이전시간에 설명을 하였고, 이번시간에는 매크로 선언과 #define의 실제 예 몇 가지에 대한 설명을 하고자 한다. 위의 예제에서와 같이 매크로 선언은 아무런 값이나 대체 하는 것 없이 단순이 선언하는 것이다. 간단하면서 특별히 사용될 것 같아 보이지 않지만, 무수히 많이 사용되고 있으며, 프로그램을 더욱 강력하게 하는 효과가 있다.

매크로 선언은 #if, #else, #ifdef, #ifndef, #undef, #endif와 보통 같이 사용한다.
간단하게 설명을 하면

#if _MACRO_DEFINED_
...
#else
...
#endif

이는 #if문이 있기 전에 #define _MACRO_DEFINED_이 선언되어 있었다면 #if문 내부가 처리가 될 것이고 그렇지 않다면 #else 문이 처리가 될 것이다. 기본적인 if, else 구문과 동일하다. 차이점이 있다면 #if, #else는 preprocess command이기 때문에 preprocessor에 의해 컴파일 되기 전에 처리가 된다. 즉, #if문이 옳다면 #else 구문은 주석과 같이 컴파일 전에 제거되어버린다.

#if, #ifdef는 동일하다.
#ifndef는 매크로 선언이 되어 있지 않으면 TRUE가 된다.
#undef는 매크로 선언을 제거한다.
#endif는 #if, #ifdef, #ifndef의 마지막에 반드시 종료의 의미로 넣어야 한다.

이때 #ifdef _OS_WINDOWS_ && _DEBUG 는 에러가 발생한다. #ifdef는 한 개의 선언에 대해서만 처리가 된다. 두개이상의 선언에 대해서 처리를 하기 위해서는 #if를 이용해야한다.
#if defined(_OS_WINDOWS_) && defined(_DEBUG)
#if !defined(_OS_WINDOWS_) || !defined(_DEBUG)

그럼 이를 이용한 몇 가지 사용 예제를 살펴보도록 하자.
1.#include 중복 호출 방지
class A {
...
};

서로 다른 파일에서 #include "A.h“가 두 번 이상 header file이 #include된다면(매우 많이 발생), "error C2011: 'CA' : 'class' type redefinition"이라는 에러가 발생한다. 모든 header file은 한번만 #include가 되는 것을 보장해야만 한다. 이를 위해서 #define 문이 이용된다.

//A.h
#ifndef _A_H_
#define _A_H_
class A {
...
};
#endif

Visual C++에서 자동적으로 만들어지는 class에서도 이렇게 두 번 #include가 되는 것을 막는 것을 볼 수 있다.
#if !defined(AFX_TESTCLASS_H__06C6084A_8E71_4601_89F7_27DE3FF1A90A__INCLUDED_)
#define AFX_TESTCLASS_H__06C6084A_8E71_4601_89F7_27DE3FF1A90A__INCLUDED_


class TestClass
{
public:
TestClass();
virtual ~TestClass();
};

#endif

2.운영체제, 언어, Debug모드 등에 범용적인 프로그램을 위해 많이 사용
#define _OS_WINDOWS_
#ifdef _OS_WINDOWS_
...
#else
...
#endif

Windows와 Linux에서 동작하는 하나의 소스를 만들기 위해서 각각의 OS에 동작하는 코드를 위를 이용하여 분리하여 작성에 이용

#ifdef _DEBUG
...
#endif

Debug 모드에서만 동작하는 소스(디버깅에 보통 이용)를 위해 이용

double* data = NULL;
#ifdef __cplusplus
data = new double[10];
#else
data = (double*)malloc(sizeof(double)*10);
#endif

C와 C++에서 동작하는 하나의 소스를 작성하기 위해 이용

이때 _DEBUG, __cplusplus는 Visual C++에서 미리 정의되어 있는 것으로 Debug모드로 설정을 하면 #define _DEBUG이 내부적으로 선언이 된다는 것이다.

3.#undef를 이용한 예제
#define SIZE 10
double data1[SIZE];
#undef SIZE
#define SIZE 20
double data2[SIZE];

#define MUL(a, b) ((a)*(b))
printf("%d", MUL(2, 3));
#undef MUL
#define MUL(a, b, c) ((a)*(b)*(c))
printf("%d", MUL(2, 3, 4));

4.문자열의 결합
#define DIR "C:\temp\"
#define FILE "test.txt"
#define PATH DIR FILE
printf("%s ", PATH); //"C: emp est.txt"

5.define의 memory 사용 예
#define A 10
printf("%dbytes", sizeof(A)); //4bytes(int)
#define B 10.0
printf("%dbytes", sizeof(B)); //8bytes(double)
#define C "simple21"
printf("%dbytes", sizeof(C)); //9bytes(string)

6.#와 ##을 함께 이용
#define PRINT(format, x) printf("x = %"#format" ", x)
int integer = 5;
PRINT(d, integer); //printf("x = %d , x);
char *string = "simple21";
PRINT(s, string); //printf("x = %s , x);

#define에서 사용할 수 있는 기호로써 #는 문자로 변경하는 기호이고, ##은 token을 합치는 기호(문자열을 합치는 기호가 아님)이다.
#define PRINT(format, x) printf("x = %"#format" ", x)
//#format은 format 변수이름을 문자열로 변경

#define FFF(a) func(#a, a)
void func(char* name, int var) {
printf("i: %s - %d ", name, var);
}
void func(char* name, double var) {
printf("f: %s - %f ", name, var);
}
int nn1 = 10;
FFF(nn1); //func("nn1", 10); => "i: nn1 - 10"
double nn2 = 10.0;
FFF(nn2); //func("nn2", 10.0); => "i: nn2 - 10.00000"

#define int2long(n) (n ## L)
int2long(10); //10L
#define BC 10
#define A B ## C //A=BC=10

7.typedef와 동일한 의미로 이용
typedef int WORD
#define WORD int
는 일반적으로 동일하다.
WORD var 5;
라고 하면 이는 int var 5;와 동일하다.
typedef int WORD는 int형과 같은 WORD형 타입을 하나 만드는 것이고, #define WORD int는 WORD라는 단어를 int라는 단어로 컴파일 전(preprocess는 컴파일 전에 실행)에 변경되기 때문에 비슷하게 동작을 한다. 하지만 차이점이 있는데, 이는 마지막에 다시 한 번 설명을 하도록 한다.

※ 매크로 상수와 함수는 되도록이면 사용하지 않는 것이 좋다. 이유는 scope이 전역적이고, type이 명시적이지 않기 때문이다. 하지만 다른 사람들의 소스를 이해하기 위해서는 알아둘 필요가 있다.

class A {
#define SIZE 10
int a[SIZE];
}

#include "A.h"
class B {
#define SIZE 20
int a[SIZE];
}

이때 #define SIZE는 전역적이기 때문에 class A와 class B에서 동일하게 적용되므로 #define SIZE 20에서 선언이 충돌 에러가 발생을 한다. 때문에 아래와 같이 복잡하게 변경을 해야 정상적으로 동작을 한다.
#include "A.h"
class B {
#ifdef SIZE
#undef SIZE
#endif
#define SIZE 20
int a[SIZE];
}

이를 위해서 enum, const(const int SIZE = 10;}를 이용하기를 매우 권장한다.
class A {
enum {SIZE=10};
int a[SIZE];
}

#include "A.h"
class B {
enum {SIZE=20};
int a[SIZE];
}

이때 enum은 전역적이지 않기 때문에 각각의 class에서만 사용가능하므로, 자신의 class에 맞는 설정을 할 수가 있다.

또한 typedef와 #define에서도 차임점이 있다.
void func() {
#define MYINT int
}
void main() {
MYINT a = 0;
}
#define은 전연적이므로 main의 MYINT a = 0;은 int a=0;으로 변환되어 아무런 문제가 없다. 하지만
void func() {
typedef int MYINT;
}
void main() {
MYINT a = 0;
}
이는 typedef는 지역적이므로 func()내에서만 유효하기 때문에 MYINT a = 0;에서 에러가 발생을 한다. 이는 #define이 더 좋아 보이지만, typedef는 자신의 scope 범위를 가지기 때문에 다른 class와의 충돌이 전혀 발생하지 않는다.

마지막으로 정리를 하면 매크로 상수의 경우 enum, const를 이용, 매크로 함수의 경우 inline함수를 이용, typedef와 유사하게 동작하는 #define은 typedef를 이용하고, 매크로 선언은 잘 이용을 하면 좋은 프로그램을 작성할 수 있다.
Posted by sally | 2006/08/20 23:18 | programming | 트랙백(8) | 덧글(1)
트랙백 주소 : http://simple21.egloos.com/tb/2411787
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Tracked from Buy xanax wi.. at 2008/04/27 08:00

제목 : Buy 180 xanax.
Buy 180 xanax 2mg. Buy xanax without prescription in usa. Buy xanax precrition needed. Buy xanax with no prescription....more

Tracked from Debt Consoli.. at 2008/08/20 21:22

제목 : Hey cool site.
Wasn't looking for your site, but great stuff....more

Tracked from Trikke at 2009/01/30 13:16

제목 : just stopped in.
Looking for something else, but nice site....more

Tracked from Jumping Shoes at 2009/02/06 04:24

제목 : just wandered in.
Looking for another site, but cool site. Thanks....more

Tracked from LocalAdLink at 2009/02/08 11:25

제목 : just stopped by.
Looking for something else, but cool site....more

Tracked from Trikke at 2009/02/14 06:06

제목 : Heya
Very nice site. All the best....more

Tracked from Malpractice at 2009/02/16 08:07

제목 : Heya
Gotta love msn, very fine stuff. Thank you....more

Tracked from Trikke at 2009/02/16 11:28

제목 : Heya
Very nice site. All the best....more

Commented by thx at 2008/09/11 09:59
thanks. 퍼갑니다.^^

:         :

:

비공개 덧글

◀ 이전 페이지 다음 페이지 ▶



Get off my back
by sally
rss

skin by 에셈