【问题标题】:Writing prototypes instead of #include <stdio.h>编写原型而不是#include <stdio.h>
【发布时间】:2016-04-06 05:01:31
【问题描述】:

例如,这里是一个“hello, world”程序,不包含stdio.h

int puts(const char *str);

int main(void)
{
    puts("hello, world");
}

当我的程序越来越长时,我什至认为这可能是一种很好的编程风格,因为所有调用的函数都在开头明确列出。

所以我的问题是:除了为标准库函数提供原型之外,#include &lt;stdio.h&gt; 还能做什么?

【问题讨论】:

  • 某些函数可以定义为宏
  • 您可以通过浏览 C99 标准的 7.21 输入/输出 &lt;stdio.h&gt; 部分来查找 stdio.h 提供的所有内容
  • 自己声明外部函数而不是包含适当的头文件是一个非常糟糕的主意。目前尚不清楚您认为自己正在解决什么问题,但我可以向您保证,您不是。
  • 为什么要重新发明轮子?除非你有更好的解决方案
  • 这不仅增加了您需要编写的代码量,而且不具备可移植性。它甚至不能在单个编译器的版本之间移植!!我在这里看到的唯一优势是可能会提高编译速度,这可以通过预编译头文件来解决。这绝对是不是好的编程风格。

标签: c language-lawyer stdio


【解决方案1】:

C11 标准草案的(非规范性)附录 J.2 列出了以下未定义行为的示例:

— 指定为由某个标准头声明或定义的函数、对象、类型或宏在包含任何声明或定义它的头之前使用 (7.1.2)

但是,正如 Keith Thompson 所指出的,7.1.4p2 说:

2 如果可以在不引用头文件中定义的任何类型的情况下声明库函数,则也可以在不包括其关联头文件的情况下声明和使用该函数。

因此使用puts 而不包括&lt;stdio.h&gt; 确实可以以符合标准的方式完成。但是,您不能声明fputs,因为它需要一个指向FILE 的指针作为参数,而您不能以严格一致的方式进行。

此外,puts 也可能是存在 &lt;stdio.h&gt; 的宏,并在存在标头时扩展为更快的东西。

总而言之,可以正确声明而不包含头文件的函数数量并没有那么大。至于使用标头中某些类型的函数 - 如果您使用 language-lawyer 标签询问 C,答案来自标准,标准对此相当直言不讳:不要这样做,否则您的程序将不会严格遵守。

【讨论】:

  • 但是 7.1.4p2 是规范的:“如果可以在不引用头文件中定义的任何类型的情况下声明库函数,那么也允许声明函数并使用它而不包括其关联的头文件。”
  • @KeithThompson 谢谢,不知何故错过了,赞成你的。
【解决方案2】:

&lt;stdio.h&gt; 定义了 FILE 类型等。您不能在没有#include &lt;stdio.h&gt; 的情况下可移植地调用任何采用FILE* 参数或返回FILE* 结果的函数。

确实没有充分的理由自己声明任何函数而不是包含标头。

【讨论】:

    【解决方案3】:

    在使用正确的程序设计时,所有公共函数的原型都放在头文件中,所有函数定义都放在 c 文件中。这就是你编写 C 程序的方式。

    这是行业事实上的标准 C 编程方式,没有专业人士使用任何其他设计。

    您的个人偏好与此处无关,C 标准中的任何漏洞也不会允许您进行不同的设计。您应该以与世界其他地方相同的方式编写 C 程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-25
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      相关资源
      最近更新 更多