提问人: 提问时间:2/21/2009 最后编辑:jww 更新时间:6/26/2023 访问量:1157794
C语言中的“静态”是什么意思?
What does "static" mean in C?
答:
- 函数中的静态变量在调用之间保持其值。
- 静态全局变量或函数仅在声明它的文件中“可见”
(1)如果你是新手,是更陌生的话题,所以这里有一个例子:
#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
这对于函数需要在调用之间保持某些状态并且您不想使用全局变量的情况很有用。但是,请注意,应该非常谨慎地使用此功能 - 它使您的代码不是线程安全的并且更难理解。
(2) 作为“访问控制”功能被广泛使用。如果你有一个实现某些功能的 .c 文件,它通常只向用户公开几个“公共”功能。它的其余功能应该被制作,这样用户将无法访问它们。这是封装,是一个很好的做法。static
引用维基百科:
在 C 编程语言中,静态 与全局变量一起使用,并且 函数将其范围设置为 包含文件。在局部变量中, static 用于存储变量 在静态分配的内存中 而不是自动分配的 记忆。虽然语言没有 规定实现 静态分配的内存类型 内存通常保留在数据中 编译时程序的段 时间,而自动 分配的内存通常 作为瞬态调用堆栈实现。
为了回答你的第二个问题,它不像在 C# 中。
但是,在 C++ 中,也用于定义类属性(在同一类的所有对象之间共享)和方法。在 C 语言中没有类,因此此功能无关紧要。static
评论
.c
来自维基百科:
在 C 编程语言中,static 与全局变量和函数一起使用,以将其范围设置为包含文件。在局部变量中,static 用于将变量存储在静态分配的内存中,而不是自动分配的内存中。虽然该语言不规定任何一种类型的内存的实现,但静态分配的内存通常在编译时保留在程序的数据段中,而自动分配的内存通常作为瞬态调用堆栈实现。
评论
static
linkage
static
static
static
如果在函数 static 中声明变量,则其值不会存储在函数调用堆栈中,并且在再次调用该函数时仍然可用。
如果声明全局变量为 static,则其作用域将限制在声明该变量的文件中。这比常规全局稍微安全一些,常规全局全局可以在整个程序中读取和修改。
static
在不同的语境中意味着不同的东西。
您可以在 C 函数中声明静态变量。此变量仅在函数中可见,但它的行为类似于全局变量,因为它只初始化一次并保留其值。在此示例中,每次调用它时,都会打印一个递增的数字。静态变量仅初始化一次。
foo()
void foo () { static int i = 0; printf("%d", i); i++ }
静态的另一个用途是当您在 .c 文件中实现函数或全局变量,但不希望其符号在文件生成的外部可见。例如
.obj
static void foo() { ... }
简短的回答......这要视情况而定。
静态定义的局部变量在函数调用之间不会丢失其值。换句话说,它们是全局变量,但范围限定为定义它们的局部函数。
静态全局变量在定义它们的 C 文件之外不可见。
静态函数在定义它们的 C 文件之外不可见。
评论
private
这取决于:
int foo()
{
static int x;
return ++x;
}
该函数将返回 1、2、3 等,---变量不在堆栈上。
交流:
static int foo()
{
}
这意味着此函数仅在此文件中具有作用域。因此,a.c 和 b.c 可以有不同的 s,并且 foo 不会暴露给共享对象。因此,如果您在 a.c 中定义了 foo,则无法从任何其他地方访问它。foo()
b.c
在大多数 C 库中,所有“私有”函数都是静态的,而大多数“公共”函数则不是。
评论
In most C libraries all "private" functions are static and most "public" are not.
你好,我有一个关于这个问题的问题,你说,我想知道函数如何表现为公共的most
static
在 C 语言中,static 有两个含义,具体取决于其使用范围。在全局范围内,当在文件级别声明对象时,这意味着该对象仅在该文件中可见。
在任何其他作用域中,它声明一个对象,该对象将在输入特定作用域的不同时间之间保留其值。例如,如果在过程中对 int 进行删除:
void procedure(void)
{
static int i = 0;
i++;
}
“I”的值在第一次调用过程时初始化为零,并在以后每次调用该过程时保留该值。如果打印“i”,它将输出 0、1、2、3、...
如果在文件中声明此项:mytest.c
static int my_variable;
那么这个变量只能从这个文件中看到。该变量不能导出到其他任何位置。
如果在函数内部声明,则每次调用该函数时,变量的值将保留其值。
静态函数不能从文件外部导出。因此,在文件中,如果将函数和变量声明为静态,则将其隐藏。*.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;
}
编译并运行:
gcc -c a.c -o a.o
gcc -c main.c -o main.o
gcc -o main main.o a.o
输出:
m()
i = 1
si = 1
m()
i = 2
si = 2
a()
i = 3
si = 1
a()
i = 4
si = 2
解释
- 有两个单独的变量 ,每个文件一个
si
- 有一个共享变量
i
像往常一样,范围越小越好,所以如果可以的话,一定要声明变量。static
在 C 编程中,文件通常用于表示“类”,变量表示类的私有静态成员。static
标准对此有何规定
C99 N1256 草案 6.7.1 “存储类说明符”说这是一个“存储类说明符”。static
6.2.2/3 “标识符的联系”意味着:static
internal linkage
如果对象或函数的文件范围标识符的声明包含存储类说明符 static,则该标识符具有内部链接。
6.2.2/2 表示其行为类似于我们的示例:internal linkage
在构成整个程序的翻译单元和库集合中,具有外部链接的特定标识符的每个声明都表示相同的对象或功能。在一个翻译单元中,每个具有内部链接的标识符声明都表示相同的对象或功能。
其中“翻译单元是预处理后的源文件。
GCC 如何为 ELF (Linux) 实现它?
与绑定。STB_LOCAL
如果我们编译:
int i = 0;
static int si = 0;
并用以下命令拆卸符号表:
readelf -s main.o
输出包含:
Num: Value Size Type Bind Vis Ndx Name
5: 0000000000000004 4 OBJECT LOCAL DEFAULT 4 si
10: 0000000000000000 4 OBJECT GLOBAL DEFAULT 4 i
因此,绑定是它们之间唯一的显着区别。 只是它们在部分中的偏移量,因此我们预计它会有所不同。Value
.bss
STB_LOCAL
记录在 ELF 规范中,http://www.sco.com/developers/gabi/2003-12-17/ch4.symtab.html:
STB_LOCAL 本地符号在包含其定义的对象文件之外不可见。同名的本地符号可以存在于多个文件中,而不会相互干扰
这使它成为代表 .static
没有 static 的变量是 ,规范说:STB_GLOBAL
当链接编辑器组合多个可重定位的对象文件时,它不允许对具有相同名称的STB_GLOBAL符号进行多个定义。
这与多个非静态定义上的链接错误一致。
如果我们用 来启动优化,则符号将从符号表中完全删除:无论如何都不能从外部使用。TODO在没有优化的情况下,为什么要在符号表上保留静态变量?它们可以用于任何事情吗?也许是为了调试。-O3
si
另请参阅
- 与函数类似:https://stackoverflow.com/a/30319812/895245
static
- 与 相比,哪个“相反”: 如何使用 extern 在源文件之间共享变量?
static
extern
C++ 匿名命名空间
在 C++ 中,您可能希望使用匿名命名空间而不是静态命名空间,这样可以实现类似的效果,但会进一步隐藏类型定义:未命名/匿名命名空间与静态函数
这里没有介绍另一个用法,那就是作为数组类型声明的一部分,作为函数的参数:
int someFunction(char arg[static 10])
{
...
}
在此上下文中,这指定传递给此函数的参数必须是包含至少 10 个元素的类型数组。有关更多信息,请在此处查看我的问题。char
评论
arg[0]
arg[9]
static
int arr[n];
静态变量值在不同的函数调用之间持续存在,其作用域仅限于本地块 静态 var 始终以值 0 初始化
需要注意的是,函数中的静态变量在第一次进入该函数时被初始化,即使在调用完成后也会持续存在;在递归函数的情况下,静态变量只初始化一次,并且在所有递归调用中,甚至在函数调用完成后也会持续存在。
如果变量是在函数外部创建的,则意味着程序员只能在已声明变量的源文件中使用该变量。
静态变量是可以在函数中使用的特殊变量,它在调用之间保存数据,并且在调用之间不会删除数据。例如:
void func(void) {
static int count; // If you don't declare its value, it is initialized with zero
printf("%d, ", count);
++count;
}
int main(void) {
while(true) {
func();
}
return 0;
}
输出:
0, 1, 2, 3, 4, 5, ...
C 语言中的静态变量具有程序的生存期。
如果在函数中定义,则它们具有局部作用域,即只能在这些函数内部访问它们。静态变量的值在函数调用之间保留。
例如:
void function()
{
static int var = 1;
var++;
printf("%d", var);
}
int main()
{
function(); // Call 1
function(); // Call 2
}
在上面的程序中,是存储在数据段中的。它的生命周期是整个 C 程序。var
函数调用 1 后,变为 2。函数调用 2 后,变为 3。var
var
的值在函数调用之间不会被销毁。var
如果介于非静态变量和局部变量之间,它将存储在 C 程序的堆栈段中。由于函数的堆栈帧在函数返回后被销毁,因此 的值也被销毁。var
var
初始化的静态变量存储在 C 程序的数据段中,而未初始化的静态变量存储在 BSS 段中。
关于静态的另一个信息:如果一个变量是全局的和静态的,则它具有 C 程序的生命周期,但它具有文件范围。它仅在该文件中可见。
要尝试此操作,请执行以下操作:
文件1.c
static int x;
int main()
{
printf("Accessing in same file%d", x):
}
文件2.c
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
现在尝试使用以下方法链接它们:
gcc -o output file1.o file2.o
这将给出链接器错误,因为 x 的文件范围为 file1.c,并且链接器无法解析对 file2.c 中使用的变量 x 的引用。
引用:
评论
static int var = 1;
我不想回答一个老问题,但我认为没有人提到K&R在“C编程语言”的A4.1节中是如何解释它的。
简而言之,静态一词有两个含义:
- 静态是两个存储类之一(另一个是 自动)。静态对象在调用之间保持其值。在所有块之外声明的对象始终是静态的,不能自动进行。
- 但是,当关键字(大力强调它被用于
code 作为关键字)与声明一起使用,它为该对象提供内部链接,因此它只能在该翻译单元中使用。但是,如果在函数中使用关键字,则会更改对象的存储类(无论如何,该对象仅在该函数中可见)。静态的对立面是关键字,它为对象提供外部链接。
static
extern
Peter Van Der Linden 在“Expert C Programming”中给出了这两个含义:
- 在函数内部,在调用之间保留其值。
- 在函数级别,仅在此文件中可见。
评论
register
&
register
人们一直说 C 语言中的“静态”有两个含义。我提供了一种另一种查看它的方式,赋予它一个单一的含义:
- 将“静态”应用于项目会强制该项目具有两个属性:(a) 它在当前范围之外不可见;(b) 它是持久的。
它似乎有两个含义的原因是,在 C 中,可以应用“static”的每个项目都已经具有这两个属性之一,因此似乎该特定用法仅涉及另一个。
例如,考虑变量。在函数外部声明的变量已经具有持久性(在数据段中),因此应用“static”只能使它们在当前作用域(编译单元)之外不可见。相反,在函数内部声明的变量在当前作用域(函数)之外已经不可见,因此应用“static”只能使它们持久化。
将“静态”应用于函数就像将其应用于全局变量一样——代码必须是持久的(至少在语言中),因此只能更改可见性。
注意:这些注释仅适用于 C。在 C++ 中,将“static”应用于类方法确实赋予了关键字不同的含义。同样,对于 C99 数组参数扩展。
评论
static
有 2 种情况:
(1)声明的局部变量:在数据段而不是堆栈中分配。当您再次调用该函数时,其值将保留。static
(2)声明的全局变量或函数:在编译单元之外不可见(即链接时是符号表中的局部符号)。static
在 C 编程中,是一个保留关键字,它控制生存期和可见性。如果我们在函数中将一个变量声明为静态变量,那么它只会在整个函数中可见。在这种用法中,此静态变量的生存期将在函数调用时开始,并在执行该函数后销毁。您可以看到以下示例:static
#include<stdio.h>
int counterFunction()
{
static int count = 0;
count++;
return count;
}
int main()
{
printf("First Counter Output = %d\n", counterFunction());
printf("Second Counter Output = %d ", counterFunction());
return 0;
}
上面的程序将给我们这个输出:
First Counter Output = 1
Second Counter Output = 1
因为一旦我们调用该函数,它就会初始化 .当我们执行时,它将销毁 count 变量。count = 0
counterFunction
评论
0
静态变量具有一个属性,即使它们超出了其范围,也可以保留其值!因此,静态变量在其先前的作用域中保留其先前的值,并且不会在新作用域中再次初始化。
例如,看看这个—— 当程序运行时,静态 int 变量保留在内存中。当声明变量的函数调用结束时,普通变量或自动变量将被销毁。
#include<stdio.h>
int fun()
{
static int count = 0;
count++;
return count;
}
int main()
{
printf("%d ", fun());
printf("%d ", fun());
return 0;
}
这将输出:1 2
由于 1 保留在内存中,因为它被声明为静态
静态变量(如全局变量)如果未显式初始化,则初始化为 0。例如,在下面的程序中,x 的值被打印为 0,而 y 的值是垃圾。有关更多详细信息,请参阅此处。
#include <stdio.h>
int main()
{
static int x;
int y;
printf("%d \n %d", x, y);
}
这将输出:0 [some_garbage_value]
这些是我发现的主要问题,上面没有为新手解释过!
分享我对这一点的了解。
在 C 中是一个声明说明符,它分为三类:static
- 存储类:有四个类:auto、、extern 和 register。
static
- 类型限定符:如关键字:const、volatile 等。
- 类型说明符:如关键字:void、char、short、int 等。
存储类也是如此。它将确定 C 程序中每个变量的以下三个属性。static
- 存储持续时间:表示为变量分配内存和释放内存的时间。只要程序正在运行,具有存储持续时间的变量就会保持在同一内存位置。
static
- 作用域:表示程序文本中可以访问变量的部分。静态变量具有文件作用域,而不是块作用域。
- 链接:表示变量可以被程序的不同部分(或文件)共享的程度。如果在块内声明了静态变量,则它没有链接。如果静态变量在块外部声明,则它具有内部链接。内部链接使其可在单个文件中访问。
存储类对变量的影响不同,具体取决于变量是在块外部还是在块内部声明。需要逐案考虑。static
静态变量的作用域仅限于声明静态变量的文件。这也适用于静态函数。
但是,函数中声明的静态变量的作用域是不同的。它仅限于函数,如非静态变量,但它在对该函数的多次调用中保留其值。
上一个:C 中的函数指针如何工作?
下一个:如何在 C 中确定数组的大小?
评论