답변:
아니.
#define
전 처리기 토큰입니다 : 컴파일러 자체는 그것을 볼 수 없습니다.
typedef
컴파일러 토큰입니다. 전처리 기는 신경 쓰지 않습니다.
둘 중 하나를 사용하여 동일한 효과를 얻을 수 있지만 필요에 따라 적절한 것을 사용하는 것이 좋습니다.
#define MY_TYPE int
typedef int My_Type;
일이 "털이 많을"때 적절한 도구를 사용하면 제대로 작동합니다.
#define FX_TYPE void (*)(int)
typedef void (*stdfx)(int);
void fx_typ(stdfx fx); /* ok */
void fx_def(FX_TYPE fx); /* error */
void fx_def(void (*)(int) fx);
; 올바른 선언은 void fx_def(void (*fx)(int));
입니다.
#define FX_TYPE(f) void (*f)(int)
있습니다.. 그런 다음 함수를 다음과 같이 선언합니다.void fx_def(FX_TYPE(fx));
typedef
변수와 마찬가지로 범위 지정 규칙을 준수하는 반면 define
컴파일 단위가 끝날 때까지 (또는 일치하는 undef
) 까지 유효합니다 .
또한으로 수행 typedef
할 수없는 일부 작업을 수행 할 수 있습니다 define
.
예를 들면 :
typedef int* int_p1;
int_p1 a, b, c; // a, b, c are all int pointers
#define int_p2 int*
int_p2 a, b, c; // only the first is a pointer, because int_p2
// is replaced with int*, producing: int* a, b, c
// which should be read as: int *a, b, c
typedef int a10[10];
a10 a, b, c; // create three 10-int arrays
typedef int (*func_p) (int);
func_p fp; // func_p is a pointer to a function that
// takes an int and returns an int
아니요, 동일하지 않습니다. 예를 들면 :
#define INTPTR int*
...
INTPTR a, b;
전처리 후 해당 줄은 다음으로 확장됩니다.
int* a, b;
문제가 보이길 바랍니다. 단지 a
유형이있을 것이다 int *
; b
일반으로 선언됩니다 int
( *
는 유형 지정자가 아닌 선언자와 연결되어 있기 때문 입니다).
그것과 대조
typedef int *INTPTR;
...
INTPTR a, b;
이 경우, 모두 a
와 b
유형이있을 것이다 int *
.
함수 또는 배열에 대한 포인터와 같이 전 처리기 매크로로 에뮬레이션 할 수없는 typedef의 전체 클래스가 있습니다.
typedef int (*CALLBACK)(void);
typedef int *(*(*OBNOXIOUSFUNC)(void))[20];
...
CALLBACK aCallbackFunc; // aCallbackFunc is a pointer to a function
// returning int
OBNOXIOUSFUNC anObnoxiousFunc; // anObnoxiousFunc is a pointer to a function
// returning a pointer to a 20-element array
// of pointers to int
전 처리기 매크로를 사용해보십시오.
#define 은 매크로를 정의합니다.
typedef 는 유형을 정의합니다.
이제 몇 가지 차이점이 있습니다.
#define 을 사용하면 컴파일 타임에 사용할 수있는 상수를 정의 할 수 있습니다. 상수는 #ifdef 와 함께 사용 하여 코드가 어떻게 컴파일되는지 확인하고 컴파일 매개 변수에 따라 특정 코드를 특수화 할 수 있습니다. #define 을
사용 하여 미니어처 찾기 및 바꾸기 매크로 함수 를 선언 할 수도 있습니다 .
typedef 를 사용하여 유형에 별칭을 제공 할 수 있지만 ( #define 으로도 수행 할 수 있음 ) #define 상수 의 찾기 및 바꾸기 특성 때문에 더 안전 합니다.
그 외에도 사용할 유형을 선언 할 수 있지만 아직 작성중인 파일에 연결되지 않은 typedef 와 함께 포워드 선언 을 사용할 수 있습니다 .
전 처리기 매크로 ( " #define
's")는 "검색 및 바꾸기"라는 어휘 대체 도구입니다. 그들은 프로그래밍 언어에 전적으로 무관하며 당신이하려는 일을 이해하지 못합니다. 당신은 그것들을 영광스러운 복사 / 붙여 넣기 메커니즘으로 생각할 수 있습니다. 때로는 유용하지만주의해서 사용해야합니다.
Typedef는 유형에 대한 별칭을 만들 수있는 C 언어 기능입니다. 이것은 복잡한 복합 유형 (구조체 및 함수 포인터와 같은)을 읽기 쉽고 다루기 쉽게 만드는 데 매우 유용합니다 (C ++에서는 유형을 typedef 해야하는 상황도 있습니다 ).
(3)의 경우 : 가능하면 항상 전 처리기 매크로보다 언어 기능을 선호해야합니다! 따라서 항상 유형에는 typedef를 사용하고 상수에는 상수 값을 사용하십시오. 이렇게하면 컴파일러가 실제로 사용자와 의미있게 상호 작용할 수 있습니다. 컴파일러는 당신의 친구이므로 가능한 한 많이 말해야합니다. 전 처리기 매크로는 컴파일러에서 의미를 숨기는 방식으로 정반대를 수행합니다 .
사용자 지정 데이터 유형을 구현하는 데 자주 사용되지만 매우 다릅니다 (이 질문이 전부라고 가정합니다).
pmg가 언급했듯이 #define
컴파일러가 코드를보기 전에 사전 처리기 (예 : 잘라 내기 및 붙여 넣기 작업)에 typedef
의해 처리되고 컴파일러에 의해 해석됩니다.
(적어도 데이터 유형을 정의 할 때) 주요 차이점 중 하나는 typedef
보다 구체적인 유형 검사 를 허용 한다는 것 입니다. 예를 들면
#define defType int
typedef int tdType
defType x;
tdType y;
여기서 컴파일러는 변수 x를 int로 인식하지만 변수 y는 int와 크기가 같은 'tdType'이라는 데이터 유형으로 간주합니다. defType 유형의 매개 변수를 사용하는 함수를 작성한 경우 호출자는 일반 int를 전달할 수 있으며 컴파일러는 차이를 알 수 없습니다. 대신 함수가 tdType 유형의 매개 변수를 사용하는 경우 컴파일러는 함수 호출 중에 적절한 유형의 변수가 사용되었는지 확인합니다.
또한 일부 디버거는 typedef
s . 이는 모든 사용자 정의 유형을 기본 기본 유형으로 나열하는 것보다 훨씬 유용 할 수 있습니다 ( #define
대신 사용 된 경우).
아니요.
typedef 는 유형에 대한 별칭을 만드는 C 키워드입니다.
#define은 컴파일 전에 텍스트 대체 이벤트를 생성하는 전 처리기 명령어입니다. 컴파일러가 코드에 도달하면 원래 "#defined"단어가 더 이상 존재하지 않습니다. #define은 주로 매크로 및 전역 상수에 사용됩니다.
위에서 언급했듯이 #define
및 typedef 있습니다. 이에 대해 생각하는 올바른 방법은 typedef를 완전한 "캡슐화 된"유형으로 보는 것입니다. 선언 한 후에는 추가 할 수 없음을 의미합니다.
다른 유형 지정자를 사용하여 매크로 유형 이름을 확장 할 수 있지만 typedef의 유형 이름은 확장 할 수 없습니다.
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
또한 typedef의 이름은 선언의 모든 declator에 대한 유형을 제공합니다.
#define fruit int *
fruit apple, banana;
매크로 확장 후 두 번째 줄은 다음과 같습니다.
int *apple, banana;
Apple은 int에 대한 포인터이고 banana는 int입니다. 비교하면. 다음과 같은 typedef :
typedef char *fruit;
fruit apple, banana;
사과와 바나나가 동일하다고 선언합니다. 앞면의 이름은 다르지만 둘 다 문자에 대한 포인터입니다.
stdfx
에 해당 유형의 유효한 객체는 int를 받고 값을 반환하지 않는 함수에 대한 포인터입니다.