Відповіді:
Немає.
#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 *
.
Існують цілі класи typedefs, які не можна емулювати за допомогою макроса препроцесора, наприклад, покажчики на функції чи масиви:
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") - це лексичний інструмент заміни a la "пошук і заміна". Вони повністю агностики мови програмування і не розуміють, що ви намагаєтеся робити. Ви можете думати про них як про прославленого механіку копіювання / вставки - іноді це корисно, але вам слід користуватися ним обережно.
Typedefs - це мова мови C, яка дозволяє створювати псевдоніми для типів. Це надзвичайно корисно, щоб зробити складні типи складових (наприклад, структури та покажчики функцій) читабельні та оброблювані (у С ++ навіть є ситуації, коли потрібно вводити тип типу).
Для (3): Завжди слід віддавати перевагу мовним можливостям перед макросами препроцесора, коли це можливо! Тому завжди використовуйте typedefs для типів, а постійні значення для констант. Таким чином, компілятор може фактично взаємодіяти з вами значущо. Пам’ятайте, що компілятор є вашим другом, тому вам слід розповісти про це якомога більше. Препроцесорні макроси роблять навпаки, приховуючи свою семантику від компілятора.
Вони дуже різні, хоча їх часто використовують для реалізації спеціальних типів даних (саме про це я припускаю, що це питання стосується).
Як згадується 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 використовується в основному для макросів і глобальних констант.
AFAIK, No.
typedef
допомагає налаштувати "псевдонім" для існуючого типу даних. Наприклад, наприклад. typedef char chr
;
#define
- директива препроцесора, що використовується для визначення макросів або загальних підстановок шаблону. Наприклад, наприклад. #define MAX 100
, замінює всі випадки на MAX
100
Як було сказано вище, існує ключова різниця між #define
і typedef. Правильний спосіб подумати про це - розглянути typedef як повний "капсульований" тип. Це означає, що ви не можете додати його після того, як ви заявили про це.
Ви можете розширити ім'я типу макросу за допомогою інших специфікаторів типу, але не типу typedef'd:
#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 - вказівник на інт, а банан - інт. В порівнянні. типу typedef, як це:
typedef char *fruit;
fruit apple, banana;
оголошує і яблуко, і банан однаковими. Назва спереду різна, але вони обидва вказівки на знак.
Як усі казали вище, вони не однакові. Більшість відповідей вказують typedef
на вигідніші ніж #define
. Але дозвольте мені поставити плюсову точку #define
:
коли ваш код надзвичайно великий, розкиданий по багатьох файлах, краще використовувати #define
; це допомагає у читанні - ви можете просто попередньо обробити весь код, щоб побачити фактичне визначення типу змінної за місцем її декларування.
stdfx
дійсні об'єкти цього типу є вказівниками на функції, які отримують int і не повертають значення.