What does “static” mean in C?
我在C代码的不同地方看到过
(1)如果你是新手的话,是比较陌生的话题,下面是一个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <stdio.h> void foo() { int a = 10; static int sa = 10; a += 5; sa += 5; printf("a = %d, sa = %d ", a, sa); } int main() { int i; for (i = 0; i < 10; ++i) foo(); } |
印刷品:
1 2 3 4 5 6 7 8 9 10 | 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 |
这对于函数需要在调用之间保持某种状态,并且不想使用全局变量的情况非常有用。但是要小心,这个特性应该非常谨慎地使用——它会使您的代码不安全,更难理解。
(2)被广泛用作"访问控制"功能。如果您有一个实现某些功能的.c文件,它通常只向用户公开一些"公共"功能。它的其余功能应该是
引用维基百科:
In the C programming language, static
is used with global variables and
functions to set their scope to the
containing file. In local variables,
static is used to store the variable
in the statically allocated memory
instead of the automatically allocated
memory. While the language does not
dictate the implementation of either
type of memory, statically allocated
memory is typically reserved in data
segment of the program at compile
time, while the automatically
allocated memory is normally
implemented as a transient call stack.
有关详细信息,请参阅此处和此处。
为了回答你的第二个问题,这不像C。
然而,在C++中,EDCOX1(0)也用于定义类属性(在同一类的所有对象之间共享)和方法。在C中没有类,所以这个特性是不相关的。
有一个使用在需要覆盖的一部分,这是在为数组类型声明为一个函数的参数:
1 2 3 4 | int someFunction(char arg[static 10]) { ... } |
在这上下文,这是传递到该函数的参数应该提醒
简短回答…这要看情况而定。
静态定义的局部变量在函数调用之间不会丢失其值。换句话说,它们是全局变量,但作用域是它们在中定义的局部函数。
静态全局变量在定义它们的C文件之外不可见。
静态函数在定义它们的C文件之外不可见。
多变量范围的例子文件
在一个静态的知识范围,说明在多功能定义文件)。
交流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #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 ", i); printf("si = %d ", si); puts(""); } |
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
GitHub的上游。
编译和运行:
1 2 3 | gcc -c a.c -o a.o gcc -c main.c -o main.o gcc -o main main.o a.o |
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | m() i = 1 si = 1 m() i = 2 si = 2 a() i = 3 si = 1 a() i = 4 si = 2 |
解读
- 有两个独立的变量和一个
si ,每个文件 - 有一个单一的共享变量的
i
照常的,更小的范围,这是更好的,如果你能
在C编程,文件是经常用来代表"班",
说它是什么标准
C99 n1256选秀6.7.1项存储类说明符"说,"这是一个
6.2.2/3"键):
If the declaration of a file scope identifier for an object or a function contains the storage-class specifier static, the identifier has internal linkage.
6.2.2 / 2和说,在我们的例子
In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function.
在"翻译单位是一个源文件预处理后。
如何实现它的GCC 11(Linux)?
与
如果我们编译:
1 2 | int i = 0; static int si = 0; |
一个符号表和拆卸:
1 | readelf -s main.o |
输出包含:
1 2 3 | Num: Value Size Type Bind Vis Ndx Name 5: 0000000000000004 4 OBJECT LOCAL DEFAULT 4 si 10: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 i |
因此,之间的差异是唯一显着的结合。只是他们的
STB_LOCAL Local symbols are not visible outside the object file containing their definition. Local symbols of the same name may exist in multiple files without interfering with each other
这使得它一个完美的选择
没有静态变量是
When the link editor combines several relocatable object files, it does not allow multiple definitions of STB_GLOBAL symbols with the same name.
这是一致的与非静态定义在多链路错误。
如果我们有
因此,湖
- 类似的
static 函数:http:/ / / / 30319812 895245 stackoverflow.com - 一个比较
static extern ",这是相反的:我如何使用外部变量之间分享的源文件?
C + +的匿名命名空间
在C + +,你可能想使用匿名命名空间,而不是静态的,这achieves类似的效应,但继续隐藏匿名命名空间中的类型定义:unnamed /静态函数。
这取决于:
1 2 3 4 5 | int foo() { static int x; return ++x; } |
函数将返回1、2、3等---变量不在堆栈上。
答:1 2 3 | static int foo() { } |
这意味着这个函数只在这个文件中有作用域。所以A.C和B.C可以有不同的
在大多数C库中,所有"私有"功能都是静态的,而大多数"公共"功能则不是。
人们一直说C中的"静态"有两个含义。我提供了另一种查看它的方式,赋予它一个单一的含义:
- 将"static"应用于项会强制该项具有两个属性:(a)在当前范围之外不可见;(b)它是持久的。
它似乎有两个含义的原因是,在C语言中,可能应用"static"的每个项都已经具有这两个属性中的一个,因此似乎该特定用法只涉及另一个属性。
例如,考虑变量。在函数外部声明的变量已经具有持久性(在数据段中),因此应用"static"只能使它们在当前范围(编译单元)之外不可见。相反,函数内部声明的变量在当前范围(函数)之外已经不可见,因此应用"static"只能使它们持久化。
将"static"应用于函数就像将其应用于全局变量一样-代码必须是持久的(至少在语言中),因此只能更改可见性。
注意:这些注释只适用于C++中的C.,将"static"应用到类方法中确实赋予了关键字不同的含义。类似于c99数组参数扩展。
可以在C函数中声明静态变量。此变量仅在函数中可见,但其行为类似于全局变量,因为它只初始化一次并保留其值。在本例中,每次调用
1 2 3 4 5 |
静态的另一种用法是在.c文件中实现函数或全局变量,但不希望其符号在文件生成的
1 | static void foo() { ... } |
维基百科:
In the C programming language, static is used with global variables and functions to set their scope to the containing file. In local variables, static is used to store the variable in the statically allocated memory instead of the automatically allocated memory. While the language does not dictate the implementation of either type of memory, statically allocated memory is typically reserved in data segment of the program at compile time, while the automatically allocated memory is normally implemented as a transient call stack.
我不喜欢回答一个老问题,但我认为没有人在"C编程语言"的A4.1节中提到K&R是如何解释这个问题的。
简而言之,静态一词有两种含义:
Peter van der Linden在"专家C编程"中给出了这两个含义:
- 在函数内部,在调用之间保留其值。
- 在函数级别,仅在此文件中可见。
在C语言中,static有两个含义,这取决于它的使用范围。在全局范围中,当在文件级别声明对象时,意味着该对象仅在该文件中可见。
在任何其他范围中,它声明一个对象,该对象将在输入特定范围的不同时间之间保留其值。例如,如果一个int在一个过程中被删除:
1 2 3 4 5 6 | void procedure(void) { static int i = 0; i++; } |
第一次调用过程时,"i"的值初始化为零,并且每次调用过程时都保留该值。如果打印"i",它将输出一个0、1、2、3……的序列。
如果您在函数static中声明一个变量,它的值将不会存储在函数调用堆栈中,并且在您再次调用函数时仍然可用。
如果您声明一个全局变量static,它的作用域将被限制在您声明它的文件中。这比在整个程序中都可以读取和修改的常规全局设置稍安全。
如果你在一mytest.c声明本文件:
1 | static int my_variable; |
那么这个变量只能在本文件的湖泊。出口的变量不能被其他任何地方。
如果你在一个函数声明的变量的值要保持其价值的每一次函数是所谓的。
a static函数不能在美国以外的文件。在A *。这样你的文件隐藏,如果你声明变量和函数是静态的。
C中的静态变量具有程序的生存期。
如果在函数中定义,则它们具有本地作用域,即只能在这些函数中访问它们。静态变量的值在函数调用之间保留。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 | void function() { static int var = 1; var++; printf("%d", var); } int main() { function(); // Call 1 function(); // Call 2 } |
在上述程序中,
函数调用1后,
函数调用之间的
如果
初始化的静态变量存储在C程序的数据段中,而未初始化的静态变量存储在BSS段中。
关于静态的另一个信息:如果一个变量是全局的和静态的,那么它有C程序的生命周期,但是它有文件范围。它只在该文件中可见。
尝试一下:
文件1.C1 2 3 4 5 6 |
文件2.C
1 2 3 4 5 6 7 8 9 | extern int x; func() { printf("accessing in different file %d",x); // Not allowed, x has the file scope of file1.c } run gcc -c file1.c gcc -c file2.c |
现在尝试使用以下链接:
1 | gcc -o output file1.o file2.o |
它将给出一个链接器错误,因为x的文件范围为file1.c,并且链接器将无法解析对file2.c中使用的变量x的引用。
参考文献:
它是最新的静态变量在函数得到注意到在第一个输入initialized售后呼叫功能和持续甚至在已经完成的案例;递归函数中的静态变量,那么initialized只读一次。也可在persists和递归调用的呼叫后,即使已经完成的功能。
如果外部变量已创建的函数,它只是意味着程序员可以使用变量的源文件已被变量。
静态变量是您可以在函数中使用的特殊变量,它保存调用之间的数据,并且不会在调用之间删除数据。例如:
1 2 3 4 5 6 7 8 9 10 11 | 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,…
一个静态变量值之间的函数调用persists andits范围是有限的本地块一个静止无功initializes值总是0
有两种情况:
(1)声明
(2)全局变量或声明为
在C语言编程中,static是一个保留关键字,它控制生存期和可见性。如果我们在一个函数中将一个变量声明为静态变量,那么它将只在整个函数中可见。在这种用法中,静态变量的生存期将在函数调用时开始,并在函数执行后销毁。您可以看到以下示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
上面的程序将给出这个输出:第一计数器输出=1第二计数器输出=1因为一旦调用函数,它将初始化count=0。当我们执行counterfunction时,它会破坏count变量。