Чому бібліотека C використовує макроси та функції з однойменною назвою?


20

Я читаю "Стандартну бібліотеку С" П. Дж. Плаугера, яка справді цікава. У книзі пояснено не тільки, як користуватися бібліотекою, але і як вона реалізована.

Я закінчив читати ctype.hрозділ, і в заголовку функції оголошуються як макроси І функції. Наприклад

int isdigit(int);

але також

#define isdigit(c) (_Ctype[(int)(c)] & _DI)

Я не розумію, для чого використовують БОТУ?

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

Цей аспект насправді не був пояснений у книзі. Може хтось, будь ласка, пояснить?


У стандарті С нічого не змушує компілятор реалізовувати його як макрос. Макрос, швидше за все, є залишком із старих часів, коли в C не було вкладених. Хоча розумний компілятор повинен мати можливість вбудувати цю функцію за потреби, без явного вбудованого ключового слова. Тож функціональний макрос існує лише тому, що компілятор реалізував хтось, хто не був геніальним у створенні компіляторів.

Відповіді:


23

Макрос (мабуть) є більш ефективним, оскільки він не включає виклик функції. Його можна оптимізувати простіше, оскільки це просто включає пошук зміщення вказівника.

Виклик функції дозволяє пов'язувати одну і ту ж бібліотеку, навіть якщо програма була скомпільована без визначення макросу - якщо вона була складена з іншим заголовком, або просто з неправдивим оголошенням всередині вихідного файлу. Якщо, наприклад, у вас є компілятор, який має чиюсь "покращену" версію ctype.h, яка не мала макросу, функція все одно існуватиме під час виконання для використання.

Якщо ми подивимось на стандарт:

7.1.4 Використання функцій бібліотеки

Будь-яка функція, оголошена в заголовку, може бути додатково реалізована як макрос, визначений у функції, визначений у заголовку, тому якщо функція бібліотеки явно оголошена при включенні її заголовка, для забезпечення декларації не можна використовувати один із наведених нижче методів. впливає такий макрос. Будь-яке макрозначення функції може бути придушене локально, включивши ім’я функції в дужки, тому що за ім'ям не йде ліва дужка, що вказує на розширення імені функції макроса. З тієї ж синтаксичної причини дозволено приймати адресу функції бібліотеки, навіть якщо вона також визначена як макрос.

Це означає, що якщо ви пишете:

int b = (isdigit)(c);

або

int (*f)(int) = &isdigit;
int b = f(c);

то ви викликаєте фактичну функцію, а не макрос. Ви також можете юридично написати:

#undef isdigit
int b = isdigit(c);

або (у вихідному файлі, що не має #include <ctype.h>прямого або перехідного періоду):

extern int isdigit(int);
int b = isdigit(c);

Як можна скласти програму БЕЗ визначення макросу?
user619818

@ user619818, використовуючи extern int isdigit(int), наприклад,
екатмур

Просто я зрозумів, ви маєте на увазі, що у користувача немає #include <що б то не було, але натомість додає int isdigit (int); вгорі файлу реалізації. Гаразд, просто прочитайте відповідь належним чином.
user619818

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