如果函数声明不在头文件中,那么静态关键字是否必要?

问题描述 投票:2回答:3

如果函数声明不在头文件(.h)中,而是仅在源文件(.c)中,为什么需要使用static关键字?当然,如果你只在.c文件中声明它,那么其他文件就不会看到它,因为你不应该#include .c文件,对吧?

我已经阅读了很多关于此的问题和答案(例如herehere),但不能完全了解它。

c static
3个回答
5
投票

static所做的是使得无法通过头文件声明和调用其他模块中的函数。

回想一下,C中的头文件包含只是文本替换:

// bar.c
#include "header.h"

int bar()
{
    return foo() + foo();
}

// header.h
int foo(void);

得到预处理成为

int foo(void);

int bar()
{
    return foo() + foo();
}

事实上,你可以取消header.h,并且首先以这种方式写bar.c。同样,foo的定义在任何一种情况下都不需要包含标题;包括它只是添加一个检查,foo的定义和声明是一致的。

但是如果你要将foo的实现改为

static int foo()
{
    // whatever
    return 42;
}

然后foo的声明将停止工作,在模块和头文件中(因为头文件只是被替换为模块)。或者实际上,声明仍然“有效”,但它停止引用你的foo函数,当你试图调用foo时链接器会抱怨它。

使用static的主要原因是为了防止链接器冲突:即使foobar在同一个模块中,并且在模块之外没有任何东西称为foo,如果它不是static,它仍然会与任何其他非static函数foo冲突。第二个原因是优化:当函数是static时,编译器确切地知道程序的哪些部分调用它以及使用什么参数,因此它可以执行常量折叠,死代码消除和/或内联。


4
投票

static关键字将函数的可见性降低到文件范围。这意味着您无法在其他单元中本地声明该函数并使用它,因为链接器不会将其添加到全局符号表中。这也意味着您也可以在其他单位中使用该名称(您可能在每个文件中都有一个static void testOutput();,如果省略static,这是不可能的。)

根据经验,您应该尽可能地保持符号的可见性。因此,如果你不需要外面的例程(并且它不是某个接口的一部分),那么保持它static


2
投票
  1. 它允许您在不同的源文件中具有相同名称的函数,因为编译器会为每个静态函数的名称添加隐式前缀(基于函数所在文件的名称),从而防止多重定义链接错误。
  2. 它可以帮助维护代码的人知道函数不作为接口的一部分公开,并且只在文件内部使用(非静态函数可以在其他源文件中使用,即使它没有在任何头文件中声明) ,使用extern关键字)。
© www.soinside.com 2019 - 2024. All rights reserved.