Что он делает
Если вы прочитаете Стандартную библиотеку Плаугера (1992), вы увидите, что заголовок <stdio.h>
может предоставлять getchar()
и getc()
как функциональные макросы (со специальным разрешением для getc()
для оценки аргумента указателя файла более одного раза!). Однако, даже если он предоставляет макросы, реализация также обязана предоставлять фактические функции, которые выполняют ту же работу, в первую очередь, чтобы вы могли получить доступ к указателю функции с именем getchar()
или getc()
и передать его другим функциям.
То есть, делая:
#include <stdio.h>
#undef getchar
extern int some_function(int (*)(void));
int core_function(void)
{
int c = some_function(getchar);
return(c);
}
Как написано, core_function()
довольно бессмысленно, но это иллюстрирует суть. Например, вы можете сделать то же самое с макросами isxxxx()
в <ctype.h>
.
Обычно вы не хотите этого делать - обычно вы не хотите удалять определение макроса. Но когда вам нужна настоящая функция, вы можете ее заполучить. Люди, которые предоставляют библиотеки, могут эмулировать функциональность стандартной библиотеки C для хорошего эффекта.
Редко нужно
Также обратите внимание, что одной из причин, по которой вам редко требуется использовать явный #undef
, является то, что вы можете вызвать функцию вместо макроса, написав:
int c = (getchar)();
Поскольку токен после getchar
не является (
, он не является вызовом функционально-подобного макроса, поэтому он должен быть ссылкой на функцию. Аналогично, первый пример, приведенный выше, будет правильно компилироваться и запускаться даже без #undef
.
Если вы реализуете свою собственную функцию с переопределением макросов, вы можете использовать это с хорошим эффектом, хотя это может немного запутать, если не будет объяснено.
/* function.h */
…
extern int function(int c);
extern int other_function(int c, FILE *fp);
#define function(c) other_function(c, stdout);
…
/* function.c */
…
/* Provide function despite macro override */
int (function)(int c)
{
return function(c, stdout);
}
Строка определения функции не вызывает макрос, потому что токен после function
не равен (
. Строка return
вызывает макрос.