Проверить, объявлена ​​ли функция с препроцессором C?

Можно ли указать препроцессору C проверить, объявлена ​​ли функция (не макрос)? Я пробовал следующее, но это не работает:

#include <stdio.h>

int main(void)
{
#if defined(printf)
    printf("You support printf!\n");
#else
    puts("Either you don't support printf, or this test doesn't work.");
#endif
    return 0;
}

person Michael    schedule 17.11.2009    source источник
comment
Меня очень интересует причина этого. Библиотеки, с которыми вы работаете, должны быть согласованными, чтобы взять ваш пример: не будет stdio.h без printf, и если printf может быть удален в отдаленном будущем, вы не будете знать сейчас, как идет замена быть вызванным.   -  person    schedule 17.11.2009
comment
Я думаю, что это не конкретно для printf, а просто для любого имени функции. Но, если вы хотите узнать, есть ли функции, просто вызовите их — ошибка компилятора вам подскажет :-)   -  person paxdiablo    schedule 17.11.2009
comment
Моим главным стимулом было проверить наличие таких функций, как bcopy() или arc4random() (при написании кросс-платформенных программ), которые не всегда определены.   -  person Michael    schedule 17.11.2009
comment
На некоторых машинах есть функция пробела, на некоторых нет. Я понятия не имею, где это определяется. Было бы неплохо, но увы. Редактировать: оказалось, что это макрос в readline/chardefs.h.   -  person Kalle    schedule 15.04.2016


Ответы (5)


Нет. Препроцессор запускается перед компилятором C, а компилятор C обрабатывает объявления функций. Препроцессор предназначен только для обработки текста.

Однако большинство файлов заголовков содержат защитные макросы, такие как _STDIO_H_, которые вы можете проверить на этапе препроцессора. Однако это решение не является переносимым, поскольку имена макросов include guard не стандартизированы.

person laalto    schedule 17.11.2009

Если вы посмотрите на такие инструменты, как autoconf, вы увидите, что они проходят множество тестов, чтобы определить, что есть на компьютере, а что нет, чтобы правильно скомпилировать, а затем установить правильный #DEFINES.

Возможно, вы захотите взглянуть на эту модель и этот инструмент, если вы используете какую-то разновидность Unix, поскольку то, что вы хотите сделать, будет невозможно, как, несомненно, указывают другие.

person James Black    schedule 17.11.2009

Строго говоря нет, препроцессор не может сделать это сам по себе. Однако вы можете помочь ему, автоматически создав соответствующие #define.

Обычно, как упоминалось выше, вы должны использовать автоинструменты в системе типа unix. Однако вы также можете создать тот же эффект с помощью make-файла. Недавно у меня была причина обнаружить, что функция «posix_fallocate» определена в заголовках, потому что я использовал uClibc, который, казалось, опускал ее в более ранних версиях. Это работает в gnu make, но вы, вероятно, можете заставить работать подобное в других версиях:

NOFALLOC := $(shell echo "\#include <fcntl.h>\nint main() { posix_fallocate(0,0,0);}" | $(CC) -o /dev/null -Werror -xc - >/dev/null 2>/dev/null && echo 0 || echo 1)
ifeq "$(NOFALLOC)" "1"
    DFLAGS += -DNO_POSIX_FALLOCATE
endif
person Sidepipe    schedule 03.05.2018

Препроцессор — это простая программа, которая почти ничего не знает о базовом языке. Он не может определить, объявлена ​​ли функция. Даже если бы это было возможно, функция может быть определена в другой библиотеке, и символ разрешается во время компоновки, поэтому препроцессор не может помочь в этом отношении.

person dreamlax    schedule 17.11.2009

Поскольку препроцессор не знает о языке C/C++ (на самом деле он выполняет только замену текста), я предполагаю, что это невозможно. почему ты хочешь сделать это? Может быть, есть другой способ.

person Björn Pollex    schedule 17.11.2009
comment
Для полноты картины я хотел бы сделать это прямо сейчас, потому что libcmocka-dev в репозиториях apt Ubuntu 20.04, похоже, на самом деле не имеет символа assert_float_equal. - person dddJewelsbbb; 16.02.2021