우리 모두는 확실히 사용한 typedef
들과 #define
한 번에 또는 다른이야. 오늘 저는 그들과 함께 일하면서 일을 고민하기 시작했습니다.
int
다른 이름으로 데이터 유형 을 사용하려면 아래 두 가지 상황을 고려하십시오 .
typedef int MYINTEGER
과
#define MYINTEGER int
위의 상황과 마찬가지로 많은 상황에서 #define을 사용하여 일을 잘 수행 할 수 있으며 typedef를 사용하여 동일한 작업을 수행 할 수 있지만 동일한 방식은 상당히 다를 수 있습니다. #define은 typedef가 할 수없는 MACRO 작업도 수행 할 수 있습니다.
그것들을 사용하는 기본 이유는 다르지만 그들의 작업은 얼마나 다른가? 둘 다 사용할 수있는 경우 어느 것이 다른 것보다 선호되어야합니까? 또한 어떤 상황에서 다른 것보다 빠를 것이 보장됩니까? (예 : #define은 전 처리기 지시문이므로 모든 것이 컴파일 또는 런타임보다 일찍 완료됩니다).
답변
typedef
매크로가 특별히 필요한 이상한 이유가없는 한 A 가 일반적으로 선호됩니다.
매크로는 텍스트 대체를 수행하므로 코드의 의미에 상당한 폭력을 줄 수 있습니다. 예를 들면 다음과 같습니다.
#define MYINTEGER int
합법적으로 작성할 수 있습니다.
short MYINTEGER x = 42;
로 short MYINTEGER
확장 되기 때문 short int
입니다.
반면에 typedef를 사용하면 다음과 같습니다.
typedef int MYINTEGER:
name MYINTEGER
은 키워드 “int”의 텍스트 대체가 아닌 type의 다른 이름입니다 int
.
복잡한 유형 일수록 상황이 더욱 악화됩니다. 예를 들면 다음과 같습니다.
typedef char *char_ptr;
char_ptr a, b;
#define CHAR_PTR char*
CHAR_PTR c, d;
a
, b
, 및 c
모든 포인터가 있지만 d
A는 char
마지막 줄로 확장하기 때문에 :
char* c, d;
어느 것이
char *c;
char d;
(포인터 타입의 타입 정의는 일반적으로 좋은 생각은 아니지만 요점을 보여줍니다.)
또 다른 이상한 경우 :
#define DWORD long
DWORD double x; /* Huh? */
답변
지금까지 매크로의 가장 큰 문제는 범위가 지정되지 않았다는 것입니다. 이것만으로 typedef의 사용을 보증합니다. 또한 의미 적으로 더 명확합니다. 코드를 읽는 사람이 정의를 볼 때 코드를 읽고 전체 매크로를 이해할 때까지 코드의 내용을 알 수 없습니다. typedef는 형식 이름이 정의 될 것을 독자에게 알려줍니다. (C ++에 대해 이야기하고 있다고 언급해야합니다. C에 대한 typedef 범위 지정에 대해서는 확실하지 않지만 비슷합니다.)
답변
소스 코드는 주로 동료 개발자를 위해 작성되었습니다. 컴퓨터는 컴파일 된 버전을 사용합니다.
이 관점 typedef
에서 #define
그렇지 않은 의미가 있습니다.
답변
Keith Thompson의 답변 은 매우 훌륭하며 범위 지정에 대한 Tamás Szelei의 추가 요점 과 함께 필요한 모든 배경을 제공해야합니다.
항상 매크로를 절망의 최후의 수단으로 생각해야합니다. 매크로로만 할 수있는 일이 있습니다. 그럼에도 불구하고, 정말로하고 싶다면 길고 열심히 생각해야합니다. 미묘하게 손상된 매크로로 인해 발생할 수있는 디버깅의 어려움은 상당하며 사전 처리 된 파일을 살펴볼 수 있습니다. C ++에서 문제의 범위에 대한 느낌을 얻으려면 한 번만 수행하는 것이 좋습니다. 전처리 된 파일의 크기 만 눈에 띄는 것일 수 있습니다.
답변
#define은 이미 제공된 범위 및 텍스트 대체에 대한 모든 유효한 설명 외에도 typedef와 완전히 호환되지 않습니다! 즉, 함수 포인터의 경우에 관한 것입니다.
typedef void(*fptr_t)(void);
이것은 type fptr_t
의 함수에 대한 포인터 인 type 을 선언합니다 void func(void)
.
이 유형은 매크로로 선언 할 수 없습니다. #define fptr_t void(*)(void)
분명히 작동하지 않습니다. #define fptr_t(name) void(*name)(void)
C 언어에서는 의미가 없으므로 생성자가없는 모호한 것을 작성해야합니다 .
#define으로 배열 포인터를 선언 할 수 없습니다. typedef int(*arr_ptr)[10];
C는 언급 할 가치가있는 유형 안전에 대한 언어 지원을 제공하지 않지만 typedef와 #define이 호환되지 않는 또 다른 경우는 의심스러운 유형 변환을 수행하는 경우입니다. typedef를 사용하는 경우 컴파일러 및 / 또는 정적 분석기 도구에서 이러한 변환에 대한 경고를 표시 할 수 있습니다.
답변
작업을 수행하는 데 필요한 전원이 가장 적고 경고가 가장 많은 도구를 사용하십시오. #define은 전 처리기에서 평가되며 대부분 자체적으로 있습니다. typedef는 컴파일러에 의해 평가됩니다. 이름이 확인 하듯이 검사가 이루어지고 typedef는 유형 만 정의 할 수 있습니다. 따라서 귀하의 예에서 분명히 typedef로 이동하십시오.
답변
define에 대한 일반적인 논쟁 외에도 Macros를 사용하여이 함수를 어떻게 작성할 것입니까?
template <typename IterType>
typename IterType::value_type Sum(
const IterType& begin,
const IterType& end,
const IterType::value_type& initialValue)
{
typename IterType::value_type result = initialValue;
for (IterType i = begin; i != end; ++i)
result += i;
return result;
}
....
vector<int> values;
int sum = Sum(values.begin(), values.end(), 0);
이것은 명백한 예이지만, 그 함수는 더하기를 구현하는 형식의 순방향 반복 가능한 시퀀스를 합할 수 있습니다 *. 이와 같이 사용 된 Typedef는 Generic Programming 의 중요한 요소입니다 .
* 나는 이것을 여기에 썼다. 나는 그것을 독자를위한 운동으로 컴파일했다 🙂
편집하다:
이 답변은 많은 혼란을 일으키는 것처럼 보이므로 더 자세히 설명하겠습니다. STL 벡터의 정의를 살펴보면 다음과 비슷한 것을 볼 수 있습니다.
template <typename ValueType, typename AllocatorType>
class vector
{
public:
typedef ValueType value_type;
...
}
표준 컨테이너 내에서 typedef를 사용하면 (위에서 만든 것과 같은) 일반 함수가 이러한 유형을 참조 할 수 있습니다. 함수 “합계”는 용기 (유형에 템플 레이팅 std::vector<int>
되지 않은 용기 내에 유지 된 입력 (상) int
). typedef가 없으면 해당 내부 유형을 참조 할 수 없습니다.
따라서 typedef는 Modern C ++의 중심이며 매크로에서는 불가능합니다.