C语言 C中的静态函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5319361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
static function in C
提问by Cenoc
What is the point of making a function static in C?
在 C 中使函数静态化有什么意义?
回答by pmg
Making a function statichides it from other translation units, which helps provide encapsulation.
使函数static对其他翻译单元隐藏,这有助于提供封装。
helper_file.c
helper_file.c
int f1(int); /* prototype */
static int f2(int); /* prototype */
int f1(int foo) {
return f2(foo); /* ok, f2 is in the same translation unit */
/* (basically same .c file) as f1 */
}
int f2(int foo) {
return 42 + foo;
}
main.c:
主文件:
int f1(int); /* prototype */
int f2(int); /* prototype */
int main(void) {
f1(10); /* ok, f1 is visible to the linker */
f2(12); /* nope, f2 is not visible to the linker */
return 0;
}
回答by Stephen Canon
pmgis spot on about encapsulation; beyond hiding the function from other translation units (or rather, becauseof it), making functions staticcan also confer performance benefits in the presence of compiler optimizations.
pmg是关于封装的;除了对其他翻译单元隐藏函数(或者更确切地说,因为它),static在编译器优化的情况下,创建函数还可以带来性能优势。
Because a staticfunction cannot be called from anywhere outside of the current translation unit (unless the code takes a pointer to its address), the compiler controls all the call points into it.
因为static不能从当前翻译单元之外的任何地方调用函数(除非代码采用指向其地址的指针),所以编译器控制所有调用点。
This means that it is free to use a non-standard ABI, inline it entirely, or perform any number of other optimizations that might not be possible for a function with external linkage.
这意味着可以自由使用非标准 ABI、完全内联它,或执行任何数量的其他优化,这些优化对于具有外部链接的函数来说可能是不可能的。
回答by 3Doubloons
The statickeyword in C is used in a compiled file (.c as opposed to .h) so that the function exists only in that file.
staticC 中的关键字用于编译文件(.c 而不是 .h),因此该函数仅存在于该文件中。
Normally, when you create a function, the compiler generates cruft the linker can use to, well, link a function call to that function. If you use the static keyword, other functions within the same file can call this function (because it can be done without resorting to the linker), while the linker has no information letting other files access the function.
通常,当您创建一个函数时,编译器会生成链接器可以用来将函数调用链接到该函数的 cruft。如果使用 static 关键字,则同一文件中的其他函数可以调用此函数(因为它可以在不求助于链接器的情况下完成),而链接器没有任何信息可以让其他文件访问该函数。
回答by mercury0114
Looking at the posts above I would like to point one detail.
看了上面的帖子,我想指出一个细节。
Suppose our main file ("main.c") looks like this:
假设我们的主文件(“main.c”)如下所示:
#include "header.h"
int main(void) {
FunctionInHeader();
}
Now consider three cases:
现在考虑三种情况:
Case 1: Our header file ("header.h") looks like this:
#include <stdio.h> static void FunctionInHeader(); void FunctionInHeader() { printf("Calling function inside header\n"); }Then the following command on linux:
gcc main.c header.h -o mainwill succeed! Following that if one runs
./mainThe output will be
Calling function inside header
Which is what that static function should print.
Case 2: Our header file ("header.h") looks like this:
static void FunctionInHeader();and we also have one more file "header.c", which looks like this:
#include <stdio.h> #include "header.h" void FunctionInHeader() { printf("Calling function inside header\n"); }Then the following command
gcc main.c header.h header.c -o mainwill give an error.
Case 3:
Similar to case 2, except that now our header file ("header.h") is:
void FunctionInHeader(); // keyword static removedThen the same command as in case 2 will succeed, and further executing ./main will give the expected result.
案例 1:我们的头文件(“header.h”)看起来像这样:
#include <stdio.h> static void FunctionInHeader(); void FunctionInHeader() { printf("Calling function inside header\n"); }然后在linux上执行以下命令:
gcc main.c header.h -o main会成功!接下来,如果一个运行
./main输出将是
标题内的调用函数
这是静态函数应该打印的内容。
案例 2:我们的头文件(“header.h”)看起来像这样:
static void FunctionInHeader();我们还有一个文件“header.c”,它看起来像这样:
#include <stdio.h> #include "header.h" void FunctionInHeader() { printf("Calling function inside header\n"); }然后下面的命令
gcc main.c header.h header.c -o main会报错。
案例3:
与情况 2 类似,除了现在我们的头文件(“header.h”)是:
void FunctionInHeader(); // keyword static removed然后与情况 2 相同的命令将成功,进一步执行 ./main 将给出预期的结果。
So from these tests (executed on Acer x86 machine, Ubuntu OS) I made an assumption that
因此,从这些测试(在 Acer x86 机器、Ubuntu OS 上执行)中,我假设
static keyword prevents function to be called in another *.c file than where it is defined.
static 关键字可防止在另一个 *.c 文件中调用函数而不是在定义它的位置。
Correct me if I am wrong.
如果我错了,请纠正我。
回答by Computer Systems
C programmers use the static attribute to hide variable and function declarations inside modules, much as you would use public and private declarations in Java and C++. C source files play the role of modules. Any global variable or function declared with the static attribute is private to that module. Similarly, any global variable or function declared without the static attribute is public and can be accessed by any other module. It is good programming practice to protect your variables and functions with the static attribute wherever possible.
C 程序员使用静态属性来隐藏模块内的变量和函数声明,就像您在 Java 和 C++ 中使用公共和私有声明一样。C 源文件起到模块的作用。使用 static 属性声明的任何全局变量或函数对该模块都是私有的。类似地,任何没有静态属性声明的全局变量或函数都是公共的,可以被任何其他模块访问。尽可能使用静态属性保护变量和函数是一种良好的编程习惯。
回答by human.js
pmg's answer is very convincing. If you would like to know how static declarations work at object level then this below info could be interesting to you. I reused the same program written by pmg and compiler it into a .so(shared object) file
pmg的回答很有说服力。如果您想知道静态声明如何在对象级别工作,那么下面的信息可能对您很有趣。我重用了由 pmg 编写的相同程序并将其编译成一个 .so(shared object) 文件
Following contents are after dumping the .so file into something human readable
以下内容是在将 .so 文件转储为人类可读的内容之后
0000000000000675 f1: address of f1 function
0000000000000675 f1: f1 函数的地址
000000000000068c f2: address of f2(staticc) function
000000000000068c f2: f2(staticc) 函数的地址
note the difference in the function address , it means something . For a function that's declared with different address , it can very well signify that f2 lives very far away or in a different segment of the object file.
注意函数地址的不同,它意味着什么。对于使用不同 address 声明的函数,它可以很好地表示 f2 位于非常远的地方或位于目标文件的不同段中。
Linkers use something called PLT(Procedure linkage table) and GOT(Global offsets table) to understand symbols that they have access to link to .
链接器使用称为 PLT(程序链接表)和 GOT(全局偏移表)的东西来理解他们有权链接到的符号。
For now think that GOT and PLT magically bind all the addresses and a dynamic section holds information of all these functions that are visible by linker.
现在想想 GOT 和 PLT 神奇地绑定了所有地址,一个动态部分保存了链接器可见的所有这些函数的信息。
After dumping the dynamic section of the .so file we get a bunch of entries but only interested in f1and f2function.
在转储 .so 文件的动态部分后,我们得到了一堆条目,但只对f1和f2函数感兴趣。
The dynamic section holds entry only for f1function at address 0000000000000675and not for f2!
动态部分仅保存地址0000000000000675处的f1函数的条目,而不保存f2 的条目!
Num: Value Size Type Bind Vis Ndx Name
Num:值大小类型绑定可视 Ndx 名称
9: 0000000000000675 23 FUNC GLOBAL DEFAULT 11 f1
And thats it !. From this its clear that the linker will be unsuccessful in finding the f2function since its not in the dynamic section of the .so file.
就是这样!。由此可见,链接器将无法成功找到f2函数,因为它不在 .so 文件的动态部分。

