Ответы:
Нет.
#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 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») - это инструмент лексической замены типа «поиск и замена». Они совершенно не зависят от языка программирования и не понимают, что вы пытаетесь сделать. Вы можете думать о них как о прославленном механизме копирования / вставки - иногда это полезно, но вы должны использовать его с осторожностью.
Typedefs - это функция языка C, которая позволяет создавать псевдонимы для типов. Это чрезвычайно полезно для того, чтобы сделать сложные составные типы (например, структуры и указатели функций) удобочитаемыми и управляемыми (в C ++ есть даже ситуации, когда вы должны ввести тип).
Для (3): вы всегда должны предпочесть языковые функции макросам препроцессора, когда это возможно! Поэтому всегда используйте typedef для типов и постоянные значения для констант. Таким образом, компилятор действительно сможет осмысленно взаимодействовать с вами. Помните, что компилятор - ваш друг, поэтому вы должны рассказать ему как можно больше. Макросы препроцессора делают прямо противоположное, скрывая вашу семантику от компилятора.
Они очень разные, хотя часто используются для реализации пользовательских типов данных (я предполагаю, что именно об этом и идет речь в этом вопросе).
Как упоминалось, pmg #define
обрабатывается препроцессором (например, операция вырезания и вставки) до того, как компилятор увидит код, и typedef
интерпретируется компилятором.
Одно из основных отличий (по крайней мере, когда дело доходит до определения типов данных) заключается в том, что он typedef
позволяет выполнять более конкретную проверку типов. Например,
#define defType int
typedef int tdType
defType x;
tdType y;
Здесь компилятор видит переменную x как int, а переменную y как тип данных, называемый tdType, который имеет тот же размер, что и int. Если вы написали функцию, которая принимает параметр типа defType, вызывающий может передать обычный int, и компилятор не заметит разницы. Если бы функция вместо этого приняла параметр типа tdType, компилятор обеспечит использование переменной правильного типа во время вызовов функции.
Кроме того, некоторые отладчики имеют возможность обрабатывать typedef
s, что может быть намного полезнее, чем перечисление всех настраиваемых типов в качестве их базовых примитивных типов (как это было бы, если бы #define
вместо этого использовались).
Нет.
Typedef - это ключевое слово C, которое создает псевдоним для типа.
#define - это инструкция препроцессора, которая создает событие замены текста перед компиляцией. Когда компилятор доходит до кода, исходного слова "#defined" больше нет. #define в основном используется для макросов и глобальных констант.
Как упоминалось выше, существует ключевое различие между #define
и typedef. Правильный способ думать об этом - рассматривать typedef как полный «инкапсулированный» тип. Это означает, что вы не можете добавлять к нему после того, как вы его объявили.
Вы можете расширить имя типа макроса другими спецификаторами типа, но не именем типа, определяемым по типу:
#define fruit int
unsigned fruit i; // works fine
typedef int fruit;
unsigned fruit i; // illegal
Кроме того, имя typedef'd предоставляет тип для каждого декларатора в объявлении.
#define fruit int *
fruit apple, banana;
После раскрытия макроса вторая строка становится такой:
int *apple, banana;
Apple - это указатель на int, а banana - на int. В сравнении. typedef вроде этого:
typedef char *fruit;
fruit apple, banana;
заявляет, что яблоко и банан одно и то же. Имя на лицевой стороне отличается, но оба они указывают на символ.
Как все говорили выше, они не такие. Большинство ответов указывают typedef
на то, что выгоднее, чем #define
. Но позвольте мне отметить плюс #define
:
когда ваш код очень большой, разбросанный по множеству файлов, его лучше использовать #define
; это помогает в удобочитаемости - вы можете просто предварительно обработать весь код, чтобы увидеть фактическое определение типа переменной в месте ее объявления.
stdfx
допустимые объекты этого типа являются указателями на функции, которые получают int и не возвращают значение.