Чи typedef та #define однакові у c?


Відповіді:


122

Немає.

#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 */

3
Після typedef stdfxдійсні об'єкти цього типу є вказівниками на функції, які отримують int і не повертають значення.
pmg

1
Чому б #define провалився у випадку вказівника функції як аргумент?
Аллахане

2
@Allahjane: розширення стає void fx_def(void (*)(int) fx);; правильна декларація void fx_def(void (*fx)(int));.
pmg

5
Покажчики на функції є здійсненними з допомогою макросів, тільки якщо ви готові відмовитися від синтаксису: #define FX_TYPE(f) void (*f)(int). Потім ви оголосите свою функцію як:void fx_def(FX_TYPE(fx));
plafer

229

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

23

Ні, вони не однакові. Наприклад:

#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

Спробуйте це зробити з макросом препроцесора.


13

#define визначає макроси.
typedef визначає типи.

Тепер, кажучи про це, ось кілька відмінностей:

За допомогою #define ви можете визначити константи, які можна використовувати під час компіляції. Константи можна використовувати за допомогою #ifdef для перевірки того, як компілюється код, та спеціалізації певного коду відповідно до параметрів компіляції.
Ви також можете використовувати #define для оголошення мініатюрних функцій пошуку та заміни макросів .

typedef може використовуватися для надання псевдонімів типам (що, можливо, ви також можете зробити з #define ), але це безпечніше через характер констант #define .
Крім того, ви можете використовувати переадресацію з typedef, що дозволяє оголосити тип, який буде використовуватися, але ще не пов'язаний з файлом, в який ви пишете.


що ви маєте на увазі під назвою та заміною характеру #define? , Дякую
Мохаммед Ель Шенаві

1
Це означає, що перед компіляцією препроцесор знайде всі макроси та замінить їх оригінальним синтаксисом
Принц Віджай Пратап

"typedef можна використовувати для надання псевдонімів для типів" Це пояснило для мене мету, дякую.
Дейв Войлес

8

Препроцесорні макроси (" #defines") - це лексичний інструмент заміни a la "пошук і заміна". Вони повністю агностики мови програмування і не розуміють, що ви намагаєтеся робити. Ви можете думати про них як про прославленого механіку копіювання / вставки - іноді це корисно, але вам слід користуватися ним обережно.

Typedefs - це мова мови C, яка дозволяє створювати псевдоніми для типів. Це надзвичайно корисно, щоб зробити складні типи складових (наприклад, структури та покажчики функцій) читабельні та оброблювані (у С ++ навіть є ситуації, коли потрібно вводити тип типу).

Для (3): Завжди слід віддавати перевагу мовним можливостям перед макросами препроцесора, коли це можливо! Тому завжди використовуйте typedefs для типів, а постійні значення для констант. Таким чином, компілятор може фактично взаємодіяти з вами значущо. Пам’ятайте, що компілятор є вашим другом, тому вам слід розповісти про це якомога більше. Препроцесорні макроси роблять навпаки, приховуючи свою семантику від компілятора.


Чи можете ви розповісти один приклад в C ++, де потрібно ввести тип? Мені просто цікаво про це.
jyz

@jyzuz: Існує щось, якщо ви хочете, щоб функція-член повернула масив функціональних покажчиків, або щось подібне - якщо ви намагаєтеся прописати тип, GCC насправді говорить "ви повинні використовувати typedef".
Керрек СБ

4

Вони дуже різні, хоча їх часто використовують для реалізації спеціальних типів даних (саме про це я припускаю, що це питання стосується).

Як згадується pmg, #defineпопередній процесор (як операція вирізання та вставки) обробляється до того, як компілятор побачить код і typedefінтерпретується компілятором.

Однією з головних відмінностей (принаймні, якщо мова йде про визначення типів даних) є те, що typedefдозволяє більш конкретно перевірити тип. Наприклад,

#define defType int
typedef int tdType

defType x;
tdType y;

Тут компілятор бачить змінну x як int, але змінну y як тип даних, який називається 'tdType', який має той самий розмір, що і int. Якщо ви написали функцію, яка приймала параметр типу defType, абонент може передати звичайний int і компілятор не знатиме різниці. Якщо функція замість цього прийняла параметр типу tdType, компілятор забезпечив би зміну відповідного типу під час викликів функції.

Крім того, деякі налагоджувачі мають можливість обробляти typedefs, що може бути набагато корисніше, ніж усі типи користувальницьких списків як їх основні примітивні типи (як це було б, якби #defineзамість цього).


2


typedef - це ключове слово C, яке створює псевдонім для типу.
#define - це передпроцесорна інструкція, яка створює подію заміни тексту перед компіляцією. Коли компілятор потрапляє до коду, оригінального слова "#defined" вже немає. #define використовується в основному для макросів і глобальних констант.


2
Використання терміна "покажчик" може призвести до певної плутанини тут.

Домовились. Ось чому я повернувся назад і додав посилання на typedef на MSDN - на всякий випадок, якщо хтось у майбутньому скористається цим питанням, щоб знайти, що таке typedef. Але, можливо, я повинен змінити це слово ...
Мандрівник Tech Guy

2

AFAIK, No.

typedefдопомагає налаштувати "псевдонім" для існуючого типу даних. Наприклад, наприклад. typedef char chr;

#define- директива препроцесора, що використовується для визначення макросів або загальних підстановок шаблону. Наприклад, наприклад. #define MAX 100, замінює всі випадки на MAX100


0

Як було сказано вище, існує ключова різниця між #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;

оголошує і яблуко, і банан однаковими. Назва спереду різна, але вони обидва вказівки на знак.


-1

Як усі казали вище, вони не однакові. Більшість відповідей вказують typedefна вигідніші ніж #define. Але дозвольте мені поставити плюсову точку #define:
коли ваш код надзвичайно великий, розкиданий по багатьох файлах, краще використовувати #define; це допомагає у читанні - ви можете просто попередньо обробити весь код, щоб побачити фактичне визначення типу змінної за місцем її декларування.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.