【问题标题】:How do I detect if stdio.h is included?如何检测是否包含 stdio.h?
【发布时间】:2015-03-18 08:54:34
【问题描述】:

我有一个头文件foo.h 声明了一个函数原型

void foo(FILE *f); 

/* ... Other things that don't depend on FILE ... */

除其他外。

显然,要使用此标头,我需要执行以下操作

#include <stdio.h>
#include "foo.h"

我想在这个特定的原型周围加上以下内容:

#ifdef _STDIO_H
void foo(FILE *f);
#endif

/* ... Other things that don't depend on FILE ... */

这样我就可以#include "foo.h" 而不必担心#include &lt;stdio.h&gt; 在我不需要该特定功能的情况下。

如果我希望我的代码可移植且符合标准,那么#ifdef _STDIO_H 是否可行?

我在标准文档中找不到_STDIO_H,但我看到它被用于各种 C 库中。我是否应该使用我知道在stdio.h 中定义的东西,比如EOF

一个相关问题:对于其他标准 C 标头,您如何处理,例如 stdlib.h

【问题讨论】:

  • 你可以这样做:struct FILE; 而不必担心包含,或检查#ifdef FILE
  • 顺便说一句,您可能会极大地混淆您的用户,这些用户恰好先包含foo.h,然后是stdio.h
  • @perreal:有很多事情可能会出错。首先,FILEstruct FILEC 中不是同一个东西。其次,我不相信标准保证struct FILE的存在。
  • @wigy 我在输入问题时意识到,最明显的问题是只需 #include &lt;stdio.h&gt; 并完成它,但这对我来说只是整洁:不包括 stdio.h 如果我在特定的源文件中不需要它。
  • 我不会将此作为答案发布,因为它不会做那件事,但您可以#include &lt;stdio.h&gt; 多次没有问题。认为stdio.h 实际上定义了宏_STDIO_H 是一个可移植性错误。你可以到达一个实际上并不#define它的系统,然后失败。

标签: c stdio


【解决方案1】:

&lt;stdio.h&gt;&lt;stdlib.h&gt; 是 C99(和 C11)标准的一部分。因此,每个(托管)符合标准的 C 实现都有它们。

在大多数实际实现中,它们是带有一些 include guards 的头文件。

符合标准的实现可能会非常具体地处理#include &lt;stdio.h&gt;,例如通过使用一些数据库。我知道没有这样的实现。

所以简单地添加

#include <stdio.h>

靠近头文件的顶部,类似于

// file foo.h
#ifndef FOO_INCLUDED
#define FOO_INCLUDED
#include <stdio.h>
// other includes ...
// ...
// other stuff
#endif /* FOO_INCLUDED */

或者,您可以不关心并记录 #include "foo.h" 需要以前的#include &lt;stdio.h&gt;;任何使用足够好的 C 实现的明智开发人员都可以解决这个问题。

其实我对Alter Mann's deleted answer的评论是错误的。它看起来像 stdin is required to be some macro,然后您可以使用 #ifdef stdin ... endif 作为 Alter Mann 正确回答。我认为它的可读性不高,您只想将 &lt;stdio.h&gt; 包含在内,要么自己将其包含在您的 foo.h 中,要么在您的文档中要求它。

与 C++ 标准头文件相反,C 标准头文件在实践中的编译速度非常快,所以我认为不值得优化 &lt;stdio.h&gt; 的异常情况 .

【讨论】:

    【解决方案2】:

    打开您的 stdio.h 文件(用于您的编译器)并查看它是否具有 _STDIO_H 或类似定义。

    【讨论】:

    • 但这不符合标准,因此成为特定于实现的。
    • 这并没有回答我的问题,因为我问是否有符合标准的方法来做到这一点,而您的解决方案取决于 C 库的供应商,而不是任何标准。
    • @Wernsey,确实如此,但解决您的问题的唯一标准方法是再次发送#include &lt;stdio.h&gt;。这样您就可以确保它已被包含在内(我知道这不是您问题的答案,您已经测试过的另一个问题是让编译器失败,并因不包含此文件而产生一些错误),如它肯定有某种保护措施,可以让你包含任意次数而不会出错。
    猜你喜欢
    • 1970-01-01
    • 2011-08-16
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    • 2013-01-26
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多