在C中,有没有一种方法可以将静态原型和公共原型放在同一个头文件中?

在C中,有没有一种方法可以将静态原型和公共原型放在同一个头文件中?,c,static,header,C,Static,Header,当我在头文件中将public和静态原型混合在一起时,编译器总是抱怨 假设我有main.h头,函数a有一个静态原型,函数b有一个正常原型。然后我想在两个.c文件中包含头文件,即main.c和other.c。在main.c中,在调用任何原型之前,我需要一个include函数 主要条款h: static int a(void); int b(void); 主要条款c: #include "main.h" void main(){ a(); } static int a(void){ /*

当我在头文件中将public和静态原型混合在一起时,编译器总是抱怨

假设我有main.h头,函数a有一个静态原型,函数b有一个正常原型。然后我想在两个.c文件中包含头文件,即main.c和other.c。在main.c中,在调用任何原型之前,我需要一个include函数

主要条款h:

static int a(void);
int b(void);
主要条款c:

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

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

int b(void){  
  /* do stuff */  
}
其他.c:

#include "main.h"
b();

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

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

关于“普通”函数,需要记住的重要一点是,同一函数的所有正向声明(
b()
,在本例中)必须匹配,否则您将遇到问题(链接错误、编译器错误,以及其他错误)。在你的情况下,他们不匹配

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


对于
静态
转发声明,它们限制了编译单元对函数的可见性。因此,在
other.c
中调用
a()
将不会执行
main.c
中实现的
a()
。这就是C中的
static
的全部要点。

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


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

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

您可以做两件事:

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

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

    如果您想要定义的“静态”函数足够短或足够便宜,您最好将其定义为静态内联的,并将其定义与其主体(不仅仅是其声明)放在一起在*.h头文件中。

    为什么在头文件中需要静态函数的原型?另外,
    void main()
    ?如果你不在嵌入式系统上工作,你需要做一些解释…@Chris我知道它应该是int。我只是想让代码尽可能小,这样我就会得到一个答案:)我很感激你努力不转储代码,但没有人会因为
    返回0而感到不快;)@克里斯:希望没有人会因为
    intmain()
    而不返回0其中之一,这是最短的。即使是那些受原始编译器困扰的人,至少也应该听说过C99;-)3.在头文件中定义静态函数。在本例中,
    a
    仅在一个TU中使用,因此它可能根本不应该在头中(2是正确的)。但是,如果您真的要在多个TU中使用
    a
    ,那么它应该在头中定义,并且可以是
    inline
    ,而不是
    static
    ,前提是您有一个支持C99的成熟编译器。