Skip to content

关键字

关键字官方解释理解场景
volatilevolatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。
遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。
意为“易变的”,用于保护一些被多个线程共享的变量,防止编译器对其进行优化,每次都从内存读取而不是CPU寄存器。1. 并行设备的硬件寄存器存储器映射的硬件寄存器
2. 中断服务程序中修改的供其它程序检测的变量
3. 多线程应用中被几个任务共享的变量
staticstatic 关键字用于定义 静态变量,它可以应用于局部变量、全局变量以及函数。意为“静态的”,static是被声明为静态类型的变量,存储在静态区(全局区)中,其生命周期为整个程序。如果是静态局部变量,其作用域为一对{}内;如果是静态全局变量,其作用域为当前文件。静态变量如果没有被初始化,则自动初始化为0。此外,static也可以修饰函数,使函数成为内部链接属性,只能在当前文件中调用。1. 需要在函数调用之间保留变量状态的局部变量(静态局部变量)
2. 限制全局变量和函数的作用域在当前文件内,避免命名冲突(静态全局变量/函数)
3. 实现单例模式,保持计数器等
externextern 关键字用于声明一个变量或函数,它告诉编译器该变量或函数在其他文件中定义,允许在当前文件中引用它们。意为“外部的”,用于声明一个变量或函数是在其他文件(或同一文件的其他位置)中定义的,而不是在当前位置定义。它主要用于实现多文件编译时的全局变量和函数的共享。1. 在一个文件中使用另一个文件中定义的全局变量
2. 在一个文件中调用另一个文件中定义的函数
3. 在头文件中声明全局变量,在源文件中定义,供多个源文件使用
constconst 关键字用于定义 常量,它指定一个变量的值不能被修改。意为“常量”、“不变的”。被const修饰的变量其值在初始化后不能被修改。它可以修饰基本类型变量、指针、函数参数和函数返回值,以提供数据完整性和安全性。1. 定义程序中不变的常量,如π、数组大小等
2. 修饰函数参数,防止函数内部修改传入的参数值
3. 修饰指针,表示指针指向的内容不可变,或指针本身不可变
4. 作为函数返回值,表示返回的值不可被修改
typedeftypedef 关键字用于为现有的数据类型创建一个新的名称(别名)。意为“类型定义”。它不创建新的类型,而是为已有的数据类型(包括结构体、联合体、枚举、基本类型)提供一个更简洁、更具可读性的别名。这有助于提高代码的可移植性和可维护性。1. 为复杂的类型声明创建别名,如结构体、函数指针
2. 提高代码的可读性,使代码更易理解
3. 提高代码的可移植性,当底层数据类型改变时,只需修改typedef定义即可
4. 减少类型名称的冗长,如为unsigned int定义UINT

变量的初始化行为

  • 全局变量: 在函数外部定义的变量,作用域贯穿整个程序。
  • 静态全局变量 : 使用 static 关键字修饰的全局变量,作用域仅限于定义它的文件。
  • 局部变量 在函数内部定义的变量,作用域仅限于定义它的函数块。
  • 静态局部变量 : 在函数内部使用 static 关键字修饰的变量,它的生命周期贯穿整个程序,但在函数外部不可见。它只在第一次执行到定义时被初始化一次。
  • 动态内存分配: 使用 new 和 delete (C++) 或 malloc 和 free (C) 在运行时分配和释放内存。
特征/变量类型全局变量 (Global)局部变量 (Local, non-static)静态局部变量 (Static Local)动态分配内存 (e.g., new/malloc)
定义位置函数外部函数内部函数内部,带 static 关键字堆 (Heap) 上,通过指针访问
存储区域数据段或 BSS 段Stack数据段或 BSS 段Heap
生命周期整个程序运行期间所在函数块执行期间 (进入时创建,退出时销毁)整个程序运行期间 (第一次执行到定义时初始化)从分配到显式释放 (delete/free)
作用域整个程序(用 extern 声明则可在所有文件中使用)定义它的函数块内部定义它的函数块内部任何能访问到指针的地方
初始化时机程序启动时进入函数块时第一次执行到定义语句时调用 newmalloc
未显式初始化时的默认值**零值 **:
- 数值类型:0
- 指针:nullptr/NULL
- 布尔:false
- 对象:调用默认构造函数 (如果存在)
**垃圾值 / 不确定值 **:
- 任何值都可能,不确定。
- 警告:访问是未定义行为!
**零值 **:
- 数值类型:0
- 指针:nullptr/NULL
- 布尔:false
- 对象:调用默认构造函数 (如果存在)
取决于分配方式:
- new Type / malloc: 垃圾值
- new Type() / new Type[N](): 零值 (对于基本类型) 或 调用默认构造函数 (对于类类型)
默认初始化机制静态初始化自动初始化静态初始化 (只发生一次)值初始化 或默认初始化
使用static关键字修饰作用域限制在当前文件,避免命名冲突。\\\
备注在整个程序中可见且生命周期最长。最常用,生命周期最短,效率高。只初始化一次,可以在函数调用之间保持状态。必须手动释放内存,否则会内存泄漏。C++ 中建议使用智能指针。

BSS段

BSS 段的存在是为了优化可执行文件的大小。如果所有未初始化的变量都在可执行文件中存储零值,那么可执行文件会变得非常大。BSS 段只需要记录这些变量所需的总大小,而不需要存储实际的零值。在程序加载到内存时,操作系统会负责将 BSS 段对应的内存区域清零。这使得可执行文件更小,加载更快。

变量类型初始化状态内存区域示例
全局变量已初始化为非零值数据段int gVar = 10;
未初始化或初始化为零值BSS 段int gUninitVar; 
 int gZeroVar = 0;
全局静态变量已初始化为非零值数据段static int sgVar = 20;
未初始化或初始化为零值BSS 段static int sgUninitVar; 
 static int sgZeroVar = 0;
局部静态变量已初始化为非零值数据段void f()
未初始化或初始化为零值BSS 段void f() { static int lsUninitVar; } 
 void f()

解释表格中的关键点:

  • **零值 对于整数类型是 0,浮点类型是 0.0,指针是 nullptr (C++) 或 NULL (C),布尔类型是 false。对于聚合类型(如结构体或类),所有成员都会递归地零初始化。
  • 垃圾值 / 不确定值: 意味着变量内存中的内容是不可预测的,可能是之前使用该内存区域的任何数据。访问这些值会导致未定义行为,程序可能崩溃,也可能产生意想不到的结果。
  • 静态初始化: 发生在程序启动时,在 main 函数执行之前。这包括零初始化和常量初始化(如果变量被常量表达式初始化)。
  • 自动初始化 : 发生在进入变量作用域时,通常在栈上完成。
  • 值初始化vs. 默认初始化:
    • 值初始化(例如 int x{};new int();)通常会导致零初始化。
    • 默认初始化(例如 int x;new int;)对于基本类型会产生垃圾值,但对于类类型会调用其默认构造函数。
  • 数据段 / BSS 段:
    • 数据段 (Data Segment): 存储已初始化的全局变量和静态变量。
    • BSS 段 (Block Started by Symbol): 存储未初始化的全局变量和静态变量。在程序加载时,这些变量被初始化为零。
  • 栈 (Stack): 存储局部变量、函数参数和函数返回地址。空间自动分配和释放。
  • 堆 (Heap): 动态内存区域,由程序员手动管理分配和释放。