检查函数是否用 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;
}
Is it possible to tell the C preprocessor to check whether a function (not a macro) is declared? I tried the following, but it doesn't appear to work:
#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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不会。预处理器在 C 编译器之前运行,C 编译器处理函数声明。预处理器仅用于文本处理。
但是,大多数头文件都包含诸如
_STDIO_H_
之类的保护宏,您可以在预处理器阶段对其进行测试。但是,该解决方案不可移植,因为包含保护宏名称未标准化。No. Preprocessor runs before the C compiler and the C compiler processes function declarations. The preprocessor is only there for text processing.
However, most header files have include guard macros like
_STDIO_H_
that you can test for in the preprocessor stage. However, that solution is not portable as the include guard macro names are not standardized.如果您查看像 autoconf 这样的工具,您会发现它们经过许多测试来确定计算机有或没有什么,正确编译,然后它们设置正确的#DEFINES。
如果您使用的是某种风格的 unix,您可能想要查看该模型和该工具,因为您想做的事情是不可能的,正如其他人无疑指出的那样。
If you look at tools like autoconf you will see that they go through many tests to determine what a computer has or doesn't have, to compile properly, then they set the correct #DEFINES.
You may want to look at that model, and that tool if you are on some flavor of unix, as what you want to do isn't going to be possible, as others undoubtedly are pointing out.
严格来说不,预处理器不能单独完成它。但是,您可以通过自动创建适当的 #define 来提供一些帮助。
通常如上所述,如果在 UNIX 类型系统上,您将使用自动工具。但是,您也可以使用 makefile 创建相同的效果。我最近有原因检测到标头中定义的“posix_fallocate”函数,因为我使用的是 uClibc,它似乎在早期版本中省略了它。这在 gnu make 中有效,但您可能可以在其他版本中得到类似的东西:
Strictly speaking no, the preprocessor can't do it on its own. However, you can give it a little help by creating appropriate #defines automatically.
Normally as was mentioned above, you'd use autotools if on a unix type system. However, you can also create the same effect using a makefile. I recently had cause to detect the "posix_fallocate" function being defined in headers, because I was using uClibc which seemed to omit it in earlier versions. This works in gnu make, but you can probably get a similar thing to work in other versions:
预处理器是一个简单的程序,对底层语言几乎一无所知。它无法判断函数是否已声明。即使可以,该函数也可能在另一个库中定义,并且该符号在链接期间解析,因此预处理器在这方面无能为力。
The preprocessor is a simple program and knows next to nothing about the underlying language. It cannot tell if a function has been declared. Even if it could, the function may be defined in another library and the symbol is resolved during linking, so the preprocessor could not help in that regard.
传统的解决方案是使用配置系统来定义宏。
但是您也可以从 C 检测原型是否存在,并将其转换为编译时整型常量表达式(适用于 _Static_asserts、常量初始值设定项、轻松消除的分支等,但不适用于预处理器) #如果条件)。
您需要
_Generic
(或在非标准__builtin_choose_expr
之前)int foo();
仍然是无原型声明并且不等效toint foo(void);
然后,您可以在类型兼容性检查中使用无原型声明如何与原型结合的属性。在 clang 上,您可能希望在本地抑制有关已弃用的非原型的警告。
下面是一个示例:
上面的结果是:
在 Linux 上,如果在
unistd.h
包含之前未定义_GNU_SOURCE
,并且如果已定义(该宏会导致
unistd.h
来公开该原型)。经测试并确认可在 clang、gcc 和tinycc 上工作。
The traditional solution has been to use a config system to define macros.
But you can detect the existence or nonexistence of a prototype from C too and turn it into a compile-time integer constant expression (suitable for
_Static_asserts
, constant initializers, easily eliminated branches, etc., though not preprocessor #if conditions).You need
_Generic
(or before that nonstandardly__builtin_choose_expr
)int foo();
is still a prototypeless declaration and not equivalent toint foo(void);
Then you can use the properties of how prototypeless declaration combine with prototypes in type compatibility checks. On clang you might want to locally suppress warnings around deprecated-non-prototypes.
Here's an example:
The above yields:
on Linux if
_GNU_SOURCE
isn't defined before theunistd.h
inclusion andif it is (the macro causes
unistd.h
to expose that prototype).Tested and confirmed to work on clang, gcc and tinycc.
由于预处理器不知道 C/C++ 语言(它实际上只进行文本替换),我猜这是不可能的。你为什么要这样做?也许还有另一种方法。
Since the preprocessor is not aware of the language C/C++ (it really only does text-replacement) I would guess that this is not possible. Why do you want to do this? Maybe there is another way.