全局变量在函数外部定义,作用域为整个文件或命名空间;局部变量在函数或复合语句内定义,作用域仅限其所在块。static局部变量生命周期全局但作用域仍局部。

全局变量和局部变量的声明位置差异
全局变量在所有函数外部定义,通常位于文件顶部或命名空间作用域内;局部变量则出现在函数内部、循环体、条件分支甚至复合语句(如 {} 块)中。
- 全局变量:写在
main()外面,哪怕在#include后面、using namespace std;下面也算全局 - 局部变量:只要在某个函数的
{}里定义,哪怕嵌套再深,也只在该作用域生效 - 特殊情况:
static局部变量虽在函数内定义,生命周期是全局的,但作用域仍是局部的——它不改变“局部变量”的归属判断
作用域规则决定访问权限
能否从某处读写一个变量,取决于当前代码点是否处于它的作用域内,而不是它有没有被初始化或有没有 extern 声明。
- 全局变量默认具有外部链接(external linkage),其他编译单元可通过
extern int g_val;引用 - 局部变量无链接性,不能被其他函数访问,哪怕同名也不会冲突(比如
int x = 10;在main()和foo()中各定义一次,互不影响) - 如果局部变量与全局变量同名,局部变量会遮蔽(shadow)全局变量——此时想访问全局版得加作用域解析符:
::g_val
常见错误:误以为“能用”就等于“是全局”
很多初学者看到变量在多个函数里都能用,就以为它是全局的,其实可能是以下几种情况:
- 忘记加
static修饰,导致局部变量未初始化而残留旧值(表现为“好像一直存在”,其实是未定义行为) - 把指针返回了局部变量地址:
int* bad() { int x = 42; return &x; }—— 这不是全局,是悬垂指针 - 使用了线程局部存储(
thread_local),它既非全局也非普通局部,但容易被误判 - 在头文件里直接定义变量(没加
inline或extern),导致多个 TU 链接时报multiple definition错误
怎么一眼识别?看定义语句所在的大括号层级
打开源码,把光标停在变量定义行,往上数大括号:
- 如果定义语句上方最近的
{属于函数(如void f() {)、lambda、类成员函数或命名空间块,那就是局部变量 - 如果定义语句上方没有匹配的
{,或者它在namespace {}顶层、文件作用域中,就是全局(或命名空间作用域)变量 - 注意宏展开干扰:有些宏会展开成变量定义,实际位置可能和你看到的不一样,必要时用
g++ -E看预处理结果
真正容易被忽略的是:C++ 没有“运行时全局变量”这种东西,所有全局变量的地址在链接阶段就确定了;而局部变量的地址每次调用都可能不同,哪怕它们名字一样、类型一样、值也一样。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











