函数内部的静态变量

时间:2018-01-20 14:53:13

标签: c memory-management

这更像是一个理论问题。 说我有以下C程序:

int a;
int f(){
    double b;
    static float c;
}

问题如下:对于每个变量(a,b,c),请命名如下:存储持续时间(生命周期),标识符范围,保存它的内存段及其初始值。

到目前为止,我已经理解了这个理论:

对于变量a

生命周期:静态

标识符范围:文件级范围

内存段:数据段

初始值:0

对于变量b

生命周期:自动(本地)

范围级别:块级别范围

内存段:stack

初始值:未定义(随机)

但是变量C让我感到困惑。 据我所知,它的生命周期是静态的,它的范围级别是块级范围,但我不确定内存段或初始值。

通常,函数的局部变量保存在堆栈段中,但由于变量是静态的,那么它应该保留在数据段中吗?

3 个答案:

答案 0 :(得分:4)

通常你不需要处理像“segment”这样的概念,它取决于文件格式(ELF,Mach-O等)。

静态变量,无论在何处定义,它们的生命周期和初始化规则都是相同的。唯一的区别是此符号对编译器和链接器的可见性。在您的特定示例中,static float c也初始化为零,就像int a一样。

从技术上讲,如果你正在处理linux和ELF格式,没有显式初始化的静态变量放在.bss段,而不是.data段。 .bss段在文件中没有物理大小,但在加载ELF文件执行时将进行零初始化。

如果您感兴趣,可以使用nm命令查看文件中的符号。

答案 1 :(得分:1)

这只是对您自己的分析和@liliscent答案的补充。变量a具有外部链接,因为它在文件级别声明,没有静态说明符。这意味着可以从不同的翻译单元访问它,前提是它被声明为extern int a;。其他变量无法从其他翻译单元访问。

答案 2 :(得分:1)

细分的概念可以指两种不同的东西: CPU看到的段,它们是段寄存器指向的内存部分的引用,或者是某种数据的名称的逻辑段(如汇编源代码中所示)。

例如,.bss段没有实际存在。它只表示:数据段的一部分初始化为零,因此不需要将其保存为程序文件中的数据。

对于其余部分,可以假设有3种段:代码,数据和堆栈,具有堆的特殊情况,它在数据段中动态分配,但这仅仅是一个实现问题,可能根据实施。

然而,出于简化的目的,可以认为所有静态变量都在数据段中分配,只有一个特性用于初始化为0的数据,这在.bss中(因此,仍然在数据中)段,但没有在程序文件中成像。)

全局和本地静态之间的唯一区别是它的可见性及其名称空间" :你可以有多个具有相同名称的静态变量,不同函数的本地变量,它们只能在声明它们的函数中看到,但在执行开始时初始化。

相反,相反,每次调用函数时,在堆栈上分配的自动变量 - 因此,如果函数被递归调用,则存在多次;静态变量由函数的所有同时实例共享。即如果一个函数调用自身并且被调用者改变了一个静态变量的值,那么该值也将被改变为调用者。