有没有办法在 C 的同一个头文件中拥有静态原型和公共原型?

Posted

技术标签:

【中文标题】有没有办法在 C 的同一个头文件中拥有静态原型和公共原型?【英文标题】:Is there a way to have static prototypes AND public ones in the same header file in C? 【发布时间】:2011-10-27 07:29:03 【问题描述】:

当我在头文件中混合 public 和静态原型时,编译器总是会发牢骚。

假设我有一个带有函数 a 的静态原型和函数 b 的普通原型的头文件 main.h。然后我想#include两个.c文件中的header,分别是main.c和other.c。在 main.c 中,我需要一个包含,因为我在任何原型之前调用该函数。

main.h:

static int a(void);
int b(void);

main.c:

#include "main.h"
void main()
  a();


static int a(void)
  /* do stuff */  


int b(void)  
  /* do stuff */  

其他.c:

#include "main.h"
b();

除了将头文件拆分为一个单独的头文件专门用于静态原型和一个用于公共原型的明显解决方案之外,最好的做法是什么?

【问题讨论】:

为什么还需要在标题中使用静态函数的原型?另外,void main()?如果你不是在嵌入式系统上工作,你需要做一些解释...... @Chris 我知道它应该是 int。只是想让代码尽可能小,所以我会得到答案:) 我很欣赏不转储代码的努力,但没有人会被return 0; 推迟;) @Chris:希望没有return 0; 也没有人会被int main() 推迟,这是最短的时间。即使是那些使用原始编译器的人,至少也应该听说过 C99 ;-) 【参考方案1】:

您不要将静态函数的声明放在头文件中。由于它们是定义它们的 .c 文件的本地文件,因此从头文件中导出它们是没有意义的。

你可以做两件事:

    在c文件中调用之前定义函数(将a()的定义移到main上面)。 在 C 文件的顶部声明静态函数(这是我个人的选择)。在您的情况下,您将 a() 的声明移动到 main.c 的顶部。

如果要在多个翻译单元中使用该函数,则可以在头文件中定义静态函数。假设你有一个支持 C99 的成熟编译器,它可以是内联的而不是静态的。

【讨论】:

3.在头文件中定义静态函数。在此示例中,a 仅在一个 TU 中使用,因此它可能根本不应该在标题中(2 是正确的)。但是,如果您实际上要在多个 TU 中使用 a,则应在标头中定义它,并且如果您有一个支持 C99 的成熟编译器,则可能有用的是 inline 而不是 static。跨度> 【参考方案2】:

在头文件中包含静态原型是没有意义的,原因是静态函数具有文件范围,因此外部的任何模块都无法访问这些函数。

相反,我建议您仅将静态原型放在文件顶部的 .c 文件中,并放在定义它们的同一文件中。

【讨论】:

【参考方案3】:

如果您在main.h 中有b() 的声明,为什么还要在包含它的other.c 中再次使用它?除此之外,一切都很好,看不到任何问题。

关于“普通”函数要记住的重要一点是同一函数的所有前向声明(在这种情况下为b())必须匹配,否则您将遇到麻烦(链接错误、编译器错误、什么不是)。在您的情况下,它们不匹配。

当然,除非b(); 是对函数的实际调用,但至少在您发布的代码中,它超出了任何范围,因此被视为前向声明。

关于static 前向声明,它们将函数的可见性限制在编译单元中。所以在other.c中调用a()不会执行在main.c中实现的a()。这就是 C 语言中 static 的全部意义所在。

【讨论】:

【参考方案4】:

如果您要定义的“静态”函数足够短或足够便宜,您最好将其定义为 static inline 并将其定义及其主体(不仅是其声明)放入*.h 头文件。

【讨论】:

以上是关于有没有办法在 C 的同一个头文件中拥有静态原型和公共原型?的主要内容,如果未能解决你的问题,请参考以下文章

为啥同一个头文件必须包含两次?

c++#ifndef 的作用,高分在线等,举例!

android app beta版和公版可以存在于同一部手机吗?

#ifdef 在同一个头文件中返回不同的值

同一个头文件中的类和类扩展名(类别)

同名的静态和实例方法?