C / C ++:头文件中的静态函数是什么意思?

我知道在源文件中声明静态函数的含义。 我在阅读一些代码,发现可以在其他文件中调用头文件中的静态函数。

Jarod asked 2020-02-13T06:08:26Z
6个解决方案
62 votes

该函数是否在头文件中定义? 这样实际的代码将直接在函数中给出,如下所示:

static int addTwo(int x)
{
  return x + 2;
}

然后,这只是为许多不同的C文件提供有用功能的一种方式。 每个包含标头的C文件都会得到自己的定义,可以调用该定义。 这当然会浪费内存,并且(在我看来)这是一件非常丑陋的事情,因为在标头中包含可执行代码通常不是一个好主意。

请记住__add_two_superquickly():ing头文件基本上只是将头文件的内容(及其包含的任何其他头文件)粘贴到C文件中,如编译器所见。 编译器永远不会知道一个特定的函数定义来自头文件。

更新:在许多情况下,执行上述操作实际上是一个好主意,而且我意识到我的回答听起来很黑白,这有点使事情简化了。 例如,可以像上面那样使用内部函数建模(或仅使用)的代码,并使用一个明确的__add_two_superquickly()关键字,甚至:

static inline int addTwo(int *x)
{
  __add_two_superquickly(x);
}

在这里,__add_two_superquickly()函数是虚构的内在函数,并且由于我们希望整个函数基本上都可以编译为一条指令,因此我们确实希望将其内联。 尽管如此,以上内容比使用宏更干净。

当然,与直接使用内部函数相比,其优势在于,通过提供另一种实现并根据所使用的编译器选择正确的函数,可以将其包装在另一层抽象中,从而可以在缺少特定内部函数的编译器上构建代码 。

unwind answered 2020-02-13T06:08:59Z
15 votes

它将有效地创建一个单独的静态函数,并在其中包含的每个cpp文件中使用相同的名称。 全局变量也是如此。

sharptooth answered 2020-02-13T06:09:20Z
7 votes

就像其他人所说的,它的含义与.c文件本身中的.h函数完全相同。 这是因为.h#include文件之间在语义上没有区别; 只有由实际传递给编译器的文件(通常名为static)组成的编译单元,并将在预处理器看到的,以static行命名的任何文件(通常名为.h)的内容插入流中。

C源位于名为.h的文件中并且公共声明位于名为.c的文件中的约定只是一个约定。 但这通常是一个不错的选择。 根据该约定,在.h文件中应该出现的唯一内容是声明,因此通常可以避免在单个程序中多次定义同一符号。

在这种特殊情况下,关键字.h使得该符号对于模块而言是私有的,因此不存在等待引起麻烦的多定义冲突。 因此从某种意义上讲,这样做是安全的。 但是,如果不能保证内联函数会被内联,则冒着风险会在发生于.c头文件的每个模块中实例化该函数的风险,充其量只是浪费了代码段中的内存。

我不确定在通用的公共头文件中有什么用例证明这样做是合理的。

如果.h文件是生成的代码,并且仅包含在单个.c文件中,那么我个人将文件命名为.h以外的其他名称,以强调它实际上根本不是公共标头。 例如,将二进制文件转换为初始化变量定义的实用程序可能会编写一个打算通过#include使用的文件,并且很可能包含该变量的static声明,甚至可能包含static访问器或其他相关实用程序的定义 功能。

RBerteig answered 2020-02-13T06:10:01Z
4 votes

如果在头文件中定义函数(而不是简单地声明它),则会在每个翻译单元(基本上在每个包含该头文件的cpp文件中)中生成该函数的副本。

这可能会增加可执行文件的大小,但是如果函数很小,则可以忽略不计。 好处是大多数编译器都可以内联函数,这可以提高代码性能。

但是这样做可能有很大的不同,而这在任何答案中都没有提到。 如果您的函数使用静态局部变量,例如:

static int counter()
{
    static int ctr = 0;
    return ctr++;
}

而不是:

//header
int counter();

//source
int counter()
{
    static int ctr = 0;
    return ctr++;
}

然后,每个包含此标头的源文件都会有其自己的计数器。 如果函数在标头中声明并在源文件中定义,则计数器将在整个程序中共享。

所以说唯一的区别将是性能和代码大小是错误的。

galinette answered 2020-02-13T06:10:44Z
1 votes

在源文件或头文件中定义没有语义上的区别,基本上,在使用static关键字限制范围的情况下,在纯C中两者的含义相同。

但是,将其写入头文件存在一个问题,这是因为每次将头包含在源文件中时,您将获得具有相同实现的函数的副本,该副本与在头中定义的普通函数非常相似 文件。 通过在标头中添加定义,您将无法实现静态功能的含义。

因此,我建议您应该仅在源文件中而不是在标头中具有实现。

answered 2020-02-13T06:11:13Z
1 votes

在某些带有小型内联函数的“仅标头”库中,它很有用。 在这种情况下,您总是想复制该函数,因此这不是一个坏模式。 但是,这为您提供了在单个头文件中插入单独的接口和实现部分的简便方法:

// header.h

// interface part (for user?!)
static inline float av(float a, float b);

// implementation part (for developer)
static inline float av(float a, float b)
{
    return (a+b)/2.f;
}

GLK框架中的Apple矢量数学库使用了此类构造(例如GLKMatrix4.h)。

mawigator answered 2020-02-13T06:11:40Z
translate from https://stackoverflow.com:/questions/780730/c-c-static-function-in-header-file-what-does-it-mean