C语言中的全局、静态、局部变量

全局变量

全局变量如果未显式初始化,通常会被放置在程序的BSS(Block Started by Symbol)段中。BSS段是可执行文件或可执行程序在内存中的一部分,它用于存储未初始化的全局变量和静态变量。BSS段在可执行文件中会占据一定的空间,但在文件被加载到内存时,操作系统会自动将BSS段中的数据初始化为零或空值。BSS段的好处是可以节省可执行文件的大小,因为未初始化的全局变量不需要在文件中保存具体的初始值。相反,它们被统一初始化为零值,当程序加载到内存时,操作系统会负责将BSS段清零。需要注意的是,如果全局变量被显式初始化,它们将被放置在数据段(data segment)中,而不是BSS段。数据段存储已经初始化的全局变量和静态变量。只有未显式初始化的全局变量才会放置在BSS段中。

如果全局变量被显式初始化,它们通常会被放置在程序的数据段(data segment)中。数据段用于存储已经初始化的全局变量和静态变量。与BSS段不同,数据段中的变量在可执行文件中会保存其具体的初始值。当程序加载到内存时,数据段中的变量会被直接使用其初始值。这意味着在可执行文件中,数据段会占据实际的空间大小,而不仅仅是一个占位符。需要注意的是,全局变量的具体放置位置可能受编译器、链接器和操作系统等因素的影响,因此不同的编译环境可能会有一些差异。
因此,通常情况下,未初始化的全局变量会放置在BSS段,已初始化的全局变量会放置在数据段。

静态变量

静态全局变量和静态局部变量区别静态全局变量和静态局部变量是两种具有不同作用域和生命周期的变量类型。
静态全局变量:

  • 作用域:静态全局变量在整个程序中都可见,可以在任何函数内部访问。
  • 生命周期:静态全局变量的生命周期与整个程序的生命周期相同,它在程序启动时被创建,在程序结束时才被销毁。
  • 存储位置:静态全局变量通常存储在数据段(data segment)中,如果没有显式初始化,它们会被放置在BSS段(Block Started by Symbol)中。
    静态局部变量:
  • 作用域:静态局部变量只在定义它的函数内部可见,不能被其他函数直接访问。
  • 生命周期:静态局部变量的生命周期在函数的整个执行过程中保持不变,即使函数执行完毕,变量的值也会被保留。
  • 存储位置:静态局部变量通常存储在数据段(data segment)中,如果没有显式初始化,它们也会被放置在BSS段(Block Started by Symbol)中。

主要区别:

  • 作用域不同:静态全局变量在整个程序中可见,静态局部变量仅在定义它们的函数内部可见。
  • 可访问性不同:静态全局变量可以被任何函数直接访问,静态局部变量只能在定义它们的函数内部访问。
  • 生命周期不同:静态全局变量的生命周期与整个程序的生命周期相同,静态局部变量在函数执行过程中保持不变。
  • 存储位置相似:通常情况下,静态全局变量和静态局部变量都存储在数据段中,可能会放置在BSS段中。

局部变量

局部变量存储在栈(Stack)中。
栈是一种用于存储局部变量和函数调用信息的数据结构,它遵循先进后出(Last-In-First-Out,LIFO)的原则。当函数被调用时,会为该函数分配一个栈帧(Stack Frame),栈帧中包含了函数的局部变量、函数的参数以及其他与函数执行相关的信息。
每当函数被调用时,就会创建一个新的栈帧,并将其推入栈的顶部。在函数执行完毕后,栈帧会被弹出,栈会回到上一个栈帧的状态,继续执行之前的函数或代码。局部变量的生命周期与所在的函数相对应。当函数执行完毕或从函数内部退出时,局部变量的内存空间会被释放,可以被其他函数使用。需要注意的是,如果局部变量被声明为静态(static)变量或带有 static 限定符,它们的存储位置将不再是栈,而是存储在静态数据段中。静态局部变量在函数执行完毕后仍然保留其值,并且在下次函数调用时保持其值不变。在 C 语言中,未初始化的全局变量和局部变量的初始值是不确定的,它们的值取决于所分配的内存区域的内容。这些变量在编译器分配内存时,不会自动初始化为特定的值。

全局变量和局部变量的初始值

对于全局变量,如果未进行初始化操作,则它们位于 BSS 段中,它们的初始值通常为零或空值。这是因为在程序加载时, BSS 段的内容会被自动初始化为零。因此,未显式初始化的全局变量会被设置为零值或空指针。

对于局部变量,未初始化的局部变量的初始值是未定义的。它们的值取决于分配给它们的内存区域的内容,这可能是之前在该内存位置上存储的数据值。因为局部变量位于栈中,栈是程序运行时分配的一段随机内存,里面的内容是不确定的。因此,在使用未初始化的局部变量之前,应该始终对其进行显式初始化,以避免出现未定义的行为。

需要注意的是,虽然全局变量和局部变量的未初始化值通常是不确定的,但编译器也可能对它们进行默认的初始化操作。例如,某些编译器可能会将未初始化的局部变量默认初始化为零。然而,为了编写更具可读性和可维护性的代码,建议始终显式初始化变量

猜你喜欢

转载自blog.csdn.net/weixin_51954217/article/details/130427468
今日推荐