我想知道为什么静态数组不需要被释放?我知道在创建动态数组时,例如
int *p;
p = malloc(10*sizeof(int));
我们必须使用以下方法释放分配的内存:
free(p);
对于函数中的静态数组,静态数组将在被调用函数完成时自动释放。
我不明白的是:使用如下函数返回静态数组时:
int *subFunc(){
static int a[5] = {1,2,3,4,5};
return a;
}
int main(){
int *p;
p = subFunc();
}
如果静态数组在完成执行后自动释放,那么我们如何才能正确访问静态数组的值?
答案 0 :(得分:43)
如果静态数组在完成执行后自动释放,那么我们如何才能正确访问静态数组的值?
不,不是那样的。 static
变量在开始main()
之前被初始化,其生命周期是程序的整个执行。因此,它们可以return
来自函数(在其中定义它们)并且仍然可以被访问。它们不是 local (对于函数),当函数完成执行时,它们会超出生命周期。
相关,引自C11
,章节§6.2.4
在没有存储类说明符的情况下声明其标识符的对象
_Thread_local
,可以是外部或内部链接,也可以是存储类 说明符static
具有静态存储持续时间。它的一生就是整个执行 在程序启动之前,程序及其存储的值只初始化一次。
关于函数内static
变量的范围,是的,它仅限于函数本身,如章节§6.2.1中所述,
[...]如果是声明符或类型说明符 声明标识符出现在块内或参数声明列表中 一个函数定义,标识符有块作用域,它终止于 相关块。 [...]
这意味着,显然,您不能在a
之外使用数组subFunc()
,因为a
在subFunc()
之外不是可见。
然而,当你return
数组时(返回数组会导致指向数组第一个元素FWIW的指针衰减),因为static
数组的生命周期是整个执行该程序,访问返回的指针(当然,在界限内)是完全有效和合法的。
答案 1 :(得分:21)
即使在它们所在的块之后,静态变量仍然存在 定义终止。因此,一个静态变量的值 函数在重复函数调用之间保留相同 功能。静态自动变量的范围与此相同 自动变量,即它是它所在的块的本地变量 定义;但是,分配的存储成为永久存储 计划的持续时间。静态变量可以在它们中初始化 声明;但是,初始化器必须是常量表达式, 并且在内存编译时只在编译时进行一次初始化 分配给静态变量。 - source
当控件来自该函数时,不会释放静态数组或变量。静态变量的范围是声明它的函数的局部变量,但它的生命周期是整个程序。
答案 2 :(得分:10)
对于子函数中的静态数组,当被调用的子函数完成时,静态数组将自动释放。
事实并非如此。输入函数时不会创建静态数组,并且在离开时不会销毁它们。
静态变量及其中的数据真的很像全局变量!该函数的唯一本地功能是名称。 (你会听到人们谈论变量的范围"这意味着"我在哪里可以使用该名称来引用它。")
因此,当您考虑静态数组的生命时,您可以在心理上取代:
int *subFunc(){
static int a[5] = {1,2,3,4,5};
return a;
}
与
int ONLY_USE_ME_INSIDE_SUBFUNC__a[5] = {1,2,3,4,5}; /* global variable */
int *subFunc(){
int * a = ONLY_USE_ME_INSIDE_SUBFUNC__a; /* a is the same as the global */
return a;
}
然后假装程序中没有其他人可以触及该全局变量。
答案 3 :(得分:3)
我想知道为什么不需要释放静态数组?
无论内存管理功能(malloc,calloc)没有分配什么,例如int a[5]
都不需要明确地处理释放。
静态变量(例如static int a[5]
)可在本地范围内访问(它们在后续本地函数调用之间保留其值)。它们是在编译时完全为此目的创建的,它们具有程序生命周期,因此即使可能,不是也不会将它们释放出来。
在其他答案中,其他所有内容都得到了巧妙的解释。
答案 4 :(得分:2)
Static variables
,通常用于通过多次调用来维护函数范围内的某些数据。它们在main()之前初始化,它们的生命周期是整个程序执行。因此,如果在退出函数后释放它们就没有意义。如果你释放它们,你将在下次调用函数时崩溃,因为它们不会被引用。