检查函数是否使用了C预处理器声明?

19

有没有可能告诉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;
}

我对此的原因非常感兴趣。你正在使用的库应该是一致的,以拾取你的例子:如果没有printf,就不会有stdio.h,如果在遥远的未来可能删除printf,你现在就不知道替换将被称为什么。 - user156676
我想这不仅仅是针对printf函数,而是适用于任何函数名称。但是,如果你想知道函数是否存在,只需调用它-编译器错误会告诉你 :-) - paxdiablo
5
我的主要动机是检查像 bcopy() 或 arc4random() 这样的函数(在编写跨平台程序时),因为它们并不总被定义。 - Michael
有些机器有“空格”功能,有些则没有。我不知道它在哪里定义。这本来是很好的,但可惜了。编辑:结果发现它是在readline/chardefs.h中的一个宏。 - Kalle
5个回答

26

没有预处理器在C编译器之前运行,而C编译器负责处理函数声明。预处理器只存在于文本处理中。

然而,大多数头文件都有包含宏卫士(如_STDIO_H_),您可以在预处理阶段进行测试。但是,该解决方案不具备可移植性,因为包含宏卫士名称未经过标准化。


5

如果你看过像autoconf这样的工具,你会发现它们经过许多测试来确定计算机有什么或没有什么,以正确编译,然后设置正确的 #DEFINES。

如果你在某个Unix系统上,可能需要看看那个模型和工具,因为其他人无疑正在指出,你想要做的事情是不可能的。


2
严格来说,预处理器不能单独完成这项任务。但是,您可以通过自动创建适当的#defines来为其提供一些帮助。
通常情况下,在Unix类型系统上,您会使用autotools。但是,您也可以使用makefile创建相同的效果。最近我需要检测头文件中是否定义了“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

1
预处理器是一个简单的程序,对底层语言几乎一无所知。它无法判断函数是否已被声明。即使它能够判断,该函数可能在另一个库中定义,并且符号在链接期间解析,因此预处理器在这方面无法提供帮助。

0

由于预处理器不了解C/C++语言(它只是进行文本替换),我猜想这是不可能的。你为什么想要这样做?也许有其他方法。


为了完整起见,我想现在就这样做,因为Ubuntu 20.04的apt存储库中的libcmocka-dev似乎没有公开assert_float_equal符号。 - dddJewelsbbb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接