void func(){
static int count; // If you don't declare its value, the value automatically initializes to zero
printf("%d, ", count);
count++;
}
void main(){
while(true){
func();
}
}
输出:
0,1,2,3,4,5 ......
1288
另请注意 static 可以以4种不同的方式使用 .
to create permanent storage for local variables in a function.
to specify internal linkage.
to declare member functions that act like non-member functions.
to create a single copy of a data member.
1
Multi-file variable scope example
这里我将说明static如何影响多个文件中函数定义的范围 .
a.c
#include <stdio.h>
/*
Undefined behavior: already defined in main.
Binutils 2.24 gives an error and refuses to link.
https://stackoverflow.com/questions/27667277/why-does-borland-compile-with-multiple-definitions-of-same-object-in-different-c
*/
/*int i = 0;*/
/* Works in GCC as an extension: https://stackoverflow.com/a/3692486/895245 */
/*int i;*/
/* OK: extern. Will use the one in main. */
extern int i;
/* OK: only visible to this file. */
static int si = 0;
void a() {
i++;
si++;
puts("a()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");
}
main.c
#include <stdio.h>
int i = 0;
static int si = 0;
void a();
void m() {
i++;
si++;
puts("m()");
printf("i = %d\n", i);
printf("si = %d\n", si);
puts("");
}
int main() {
m();
m();
a();
a();
return 0;
}
#include <stdio.h>
void foo()
{
int a = 10;
static int sa = 10;
a += 5;
sa += 5;
printf("a = %d, sa = %d\n", a, sa);
}
int main()
{
int i;
for (i = 0; i < 10; ++i)
foo();
}
这打印:
a = 15, sa = 15
a = 15, sa = 20
a = 15, sa = 25
a = 15, sa = 30
a = 15, sa = 35
a = 15, sa = 40
a = 15, sa = 45
a = 15, sa = 50
a = 15, sa = 55
a = 15, sa = 60
重要的是要注意函数中的静态变量在第一次进入该函数时初始化,并且即使在它们的调用完成之后仍然存在; in case of recursive functions the static variable gets initialized only once and persists as well over all recursive calls and even after the call of the function has been finished.
18 回答
如果在函数static中声明一个变量,它的值将不会存储在函数调用堆栈中,并且在再次调用该函数时仍然可用 .
如果声明全局变量static,则其范围将限制在您声明它的文件中 . 这比常规全局更安全,可以在整个程序中读取和修改 .
在C中,静态有两个含义,具体取决于其使用范围 . 在全局范围中,当在文件级别声明对象时,意味着该对象仅在该文件中可见 .
在任何其他范围,它声明一个对象,该对象将在输入特定范围的不同时间之间保留其值 . 例如,如果在过程中对del进行了delcared:
在第一次调用该过程时,'i'的值被初始化为零,并且每次调用该过程时都会保留该值 . 如果'i'被打印,它将输出0,1,2,3 ......的序列...
静态变量是一个可以在函数中使用的特殊变量,它在调用之间保存数据,并且不会在调用之间删除它 . 例如:
输出:
0,1,2,3,4,5 ......
另请注意
static
可以以4种不同的方式使用 .Multi-file variable scope example
这里我将说明static如何影响多个文件中函数定义的范围 .
a.c
main.c
Compile
Output
Interpretation
si
有两个独立的变量,每个文件一个i
有一个共享变量像往常一样,范围越小越好,所以如果可以,总是声明变量
static
.在C编程中,文件通常用于表示"classes",而
static
变量表示类的私有静态成员 .What standards say about it
C99 N1256 draft 6.7.1 "Storage-class specifiers"说
static
是"storage-class specifier" .6.2.2 / 3 "Linkages of identifiers"说
static
暗示internal linkage
:和6.2.2 / 2说
internal linkage
在我们的例子中表现得像:其中“翻译单位是预处理后的源文件” .
How GCC implements it for ELF (Linux)?
用
STB_LOCAL
绑定 .如果我们编译:
并用以下符号反汇编符号表:
输出包含:
所以绑定是它们之间唯一的重要区别 .
Value
只是它们在.bss
部分的偏移量,所以我们预计它会有所不同 .STB_LOCAL
记录在http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html的ELF规范中:这使它成为代表
static
的完美选择 .没有静态的变量是
STB_GLOBAL
,规范说:这与多个非静态定义上的链接错误一致 .
如果我们使用
-O3
进行优化,则si
符号将完全从符号表中删除:无论如何都无法从外部使用它 . TODO为什么在没有优化时根据符号表保留静态变量?他们可以用于任何事情吗?也许是为了调试 .See also
类似
static
函数:https://stackoverflow.com/a/30319812/895245将
static
与extern
进行比较,其中"the opposite":How do I use extern to share variables between source files?Try it yourself
Example on github给你玩 .
我不想回答一个老问题,但我认为没有人提到K&R在“C程序设计语言”的A4.1节中如何解释它 .
简而言之,单词static与 two 含义一起使用:
Static是两个存储类之一(另一个是自动存储类) . 静态对象在调用之间保持其值 . 在所有块之外声明的对象始终是静态的,不能自动生成 .
但是,当
static
keyword (强调它在代码中用作关键字)与声明一起使用时,它会为该对象提供内部链接,因此它只能在该转换单元中使用 . 但是如果关键字在函数中使用,它会更改对象的存储类(该对象只能在该函数中可见) . 与static相反的是extern
关键字,它为对象提供外部链接 .Peter Van Der Linden在“专家C编程”中给出了这两个含义:
在函数内部,在调用之间保留其值 .
在功能级别,仅在此文件中可见 .
这取决于:
该函数将返回1,2,3等 . ---变量不在堆栈上 .
a.c:
这意味着此函数仅在此文件中具有范围 . 所以a.c和b.c可以有不同的
foo()
,而foo不会暴露给共享对象 . 因此,如果您在a.c中定义了foo,则无法从b.c
或任何其他位置访问它 .在大多数C库中,所有“私有”函数都是静态的,而大多数“公共”函数则不是 .
C中的静态变量具有程序的生命周期 .
如果在函数中定义,它们具有局部范围,即只能在这些函数内访问它们 . 函数调用之间保留静态变量的值 .
例如:
在上述程序,
var
存储在数据段中 . 它的生命周期是整个C程序 .函数调用1后,
var
变为2.函数调用2后,var
变为3 .函数调用之间不会销毁
var
的值 .如果
var
介于非静态变量和局部变量之间,则它将存储在C程序的堆栈段中 . 由于函数的堆栈帧在函数返回后被销毁,因此var
的值也被销毁 .初始化的静态变量存储在C程序的数据段中,而未初始化的静态变量存储在BSS段中 .
关于static的另一个信息:如果变量是全局变量和静态变量,它具有C程序的生命周期,但它具有文件范围 . 它仅在该文件中可见 .
试试这个:
file1.c
file2.c
现在尝试使用以下方法链接它们
它会产生链接器错误,因为x具有file1.c的文件范围,并且链接器将无法解析对file2.c中使用的变量x的引用 .
参考文献:
http://en.wikipedia.org/wiki/Translation_unit_(programming)
http://en.wikipedia.org/wiki/Call_stack
来自维基百科:
静态变量值在不同的函数调用之间持续存在,并且范围仅限于本地块,静态var始终使用值0初始化
简短回答...... it depends.
静态定义的局部变量在函数调用之间不会丢失它们的值 . 换句话说,它们是全局变量,但是作用于它们定义的局部函数 .
静态全局变量在定义它们的C文件之外是不可见的 .
静态函数在定义它们的C文件之外是不可见的 .
函数内的静态变量在调用之间保持其值 .
静态全局变量或函数仅在声明的文件中为"seen"
如果你是新手,(1)是更多的外国话题,所以这是一个例子:
这打印:
这对于函数需要在调用之间保持某种状态并且您不想使用全局变量的情况很有用 . 但要注意,应该非常谨慎地使用此功能 - 它使您的代码不是线程安全的,更难理解 .
(2)广泛用作"access control"功能 . 如果您有.c文件实现某些功能,它通常只向用户公开几个"public"函数 . 其余的功能应该是
static
,这样用户将无法访问它们 . 这是封装,一个很好的做法 .引用Wikipedia:
有关详细信息,请参阅here和here .
并回答你的第二个问题,它不像在C#中 .
但是,在C中,
static
也用于定义类属性(在同一类的所有对象之间共享)和方法 . 在C中没有类,所以这个功能是无关紧要的 .重要的是要注意函数中的静态变量在第一次进入该函数时初始化,并且即使在它们的调用完成之后仍然存在; in case of recursive functions the static variable gets initialized only once and persists as well over all recursive calls and even after the call of the function has been finished.
如果变量是在函数外部创建的,则意味着程序员只能使用已声明变量的源文件中的变量 .
人们一直说C中的“静态”有两个含义 . 我提供了一种查看它的另一种方式,它具有单一含义:
它似乎有两个含义的原因是,在C中,可以应用'static'的每个项目都具有这两个属性中的一个,所以看起来好像这个特定用法只涉及另一个 .
例如,考虑变量 . 在函数之外声明的变量已经具有持久性(在数据段中),因此应用'static'只能使它们在当前范围之外不可见(编制单位) . 相反,在函数内部声明的变量已经在当前作用域(函数)之外具有不可见性,因此应用“静态”只能使它们具有持久性 .
将'static'应用于函数就像将它应用于全局变量一样 - 代码必须是持久的(至少在语言中),因此只能改变可见性 .
注意:这些注释仅适用于C.在C中,将'static'应用于类方法确实赋予关键字不同的含义 . 类似地,对于C99数组参数扩展 .
static
在不同的上下文中表示不同的东西 .foo()
时,它将打印一个递增的数字 . 静态变量只初始化一次 ..obj
之外可见 . 例如有2种情况:
(1)声明的局部变量
static
:分配在数据段而不是堆栈中 . 当您再次调用该函数时,其值将保留 .(2)声明的全局变量或函数
static
:不可见的外部编译单元(即链接期间符号表中的局部符号) .如果你在mytest.c文件中声明:
然后,只能从此文件中看到此变量 . 该变量无法在其他任何地方导出 .
如果在函数内部声明,则每次调用函数时,变量的值都将保持其值 .
无法从文件外部导出静态函数 . 因此,在* .c文件中,如果将它们声明为静态,则隐藏函数和变量 .
还有一个用途未在此处介绍,它作为数组类型声明的一部分作为函数的参数:
在此上下文中,它指定传递给此函数的参数必须是
char
类型的数组,其中至少包含10个元素 . 有关详细信息,请参阅我的问题here .