这更像是一个理论问题。 说我有以下C程序:
int a;
int f(){
double b;
static float c;
}
问题如下:对于每个变量(a,b,c),请命名如下:存储持续时间(生命周期),标识符范围,保存它的内存段及其初始值。
到目前为止,我已经理解了这个理论:
对于变量a :
生命周期:静态
标识符范围:文件级范围
内存段:数据段
初始值:0
对于变量b :
生命周期:自动(本地)
范围级别:块级别范围
内存段:stack
初始值:未定义(随机)
但是变量C让我感到困惑。 据我所知,它的生命周期是静态的,它的范围级别是块级范围,但我不确定内存段或初始值。
通常,函数的局部变量保存在堆栈段中,但由于变量是静态的,那么它应该保留在数据段中吗?
答案 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中(因此,仍然在数据中)段,但没有在程序文件中成像。)
全局和本地静态之间的唯一区别是它的可见性及其名称空间" :你可以有多个具有相同名称的静态变量,不同函数的本地变量,它们只能在声明它们的函数中看到,但在执行开始时初始化。
相反,相反,每次调用函数时,在堆栈上分配的自动变量 - 因此,如果函数被递归调用,则存在多次;静态变量由函数的所有同时实例共享。即如果一个函数调用自身并且被调用者改变了一个静态变量的值,那么该值也将被改变为调用者。