C 全局变量和局部变量

在 C 语言中,变量有一定的作用域(也就是变量的有效范围)。根据变量定义位置的不同,可以分为以下 2 种。

  • 全局变量。
  • 局部变量。

C 全局变量

在 C 语言中,全局变量指的是在所有函数之外定义的变量。对于全局变量来说,它的作用范围是从定义处到整个 C 程序结束。也就是说,程序中的任何函数都可以访问和修改全局变量的值。

示例 1:C 定义全局变量

#include <stdio.h>

// 定义全局变量
int year = 2030;
void fn(void)
{
    // 在 fn() 函数中访问全局变量
    printf("%d\n", year);
}
int main(void)
{
    fn();
    // 在 main() 函数中访问全局变量
    printf("%d", year);
    return 0;
}

运行结果如下。

2030
2030

分析:

C 语言中的全局变量在整个程序范围内有效,所有函数都可以访问和修改它。

示例 2:全局变量会默认初始化

#include <stdio.h>

// 定义全局变量
int a;
float b;
char c;

int main(void)
{
    // 在 main() 函数中访问全局变量
    printf("%d\n", a);
    printf("%f\n", b);
    printf("%c\n", c);

    return 0;
}

运行结果如下。

0
0.000000
(空字符)

分析:

如果全局变量在定义时没有显式地初始化,它们默认会被自动初始化。其中 int 类型默认初始化为 0,float 类型默认初始化为 0.000000,而 char 类型默认初始化为空字符(即 ASCII 值为 0 的字符 '\0')。

提示: 使用关键字 static 修饰的全局变量,其作用域会被限制在当前源文件内。也就是说,其他源文件无法通过 extern 关键字访问该静态全局变量。这种方式有助于实现模块化和信息隐藏。

C 局部变量

在 C 语言中,局部变量指的是在 “函数” 内部定义的变量。对于局部变量来说,它只能在其被定义的函数内部被访问到。当函数执行完毕后,局部变量会被销毁,其占用的内存也会被释放。

示例 3:C 定义局部变量

#include <stdio.h>

void fn(void)
{
    // 定义局部变量
    int year = 2030;
    // 访问局部变量
    printf("%d", year);
}
int main(void)
{
    fn();
    // 尝试在 main() 中访问局部变量
    printf("%d", year);
    return 0;
}

运行结果如下。

(报错)error: 'year' undeclared (first use in this function);

分析:

C 语言中的局部变量只能在当前函数内部可以被访问到,而无法在其他函数中被访问到。

在下面代码中,我们可以直观地看出全局变量和局部变量的位置区别。

#include <stdio.h>

int a = 10;             // 这是全局变量
void fn(void)
{
    int b = 20;         // 这是局部变量
    printf("%d", b);
}
int main(void)
{
    int c = 30;        // 这是局部变量
    printf("%d", c);
    return 0;
}

示例 4:static 局部变量

#include <stdio.h>

void counter() 
{
    // 静态局部变量,只初始化一次
    static int count = 0;
    count++;
    printf("函数被调用了 %d 次\n", count);
}

int main(void) 
{
    counter();
    counter();
    counter();
    return 0;
}

运行结果如下。

函数被调用了 1 次
函数被调用了 2 次
函数被调用了 3

分析:

使用关键字 static 修饰的局部变量,其生命周期会持续到程序结束,但其作用域仍然限制在定义它的函数内部。该静态局部变量在程序运行前就已经完成了初始化(且只能初始化一次),后续的函数调用会保持上次的值。

注意: C 语言中静态局部变量的初始值必须是常量。

C 全局变量与局部变量同名

在 C 语言中,如果在函数内部定义了一个与全局变量同名的局部变量,那么在该函数内部,局部变量会 “屏蔽” 全局变量。也就是说,函数内部访问的是局部变量,而不是全局变量。

示例 5:全局变量与局部变量同名

#include <stdio.h>

// 定义全局变量
int year = 2030;

void getYear(void) 
{
    // 定义与全局变量同名的局部变量
    int year = 2077;
    printf("%d\n", year);      // 访问的是局部变量
}

int main(void) 
{
    printf("main(修改前):%d\n", year);     // 访问的是全局变量
    getYear();
    printf("main(修改后):%d\n", year);     // 访问的仍然是全局变量

    return 0;
}

运行结果如下。

main(修改前):2030
2077
main(修改后):2030

分析:

在 getYear() 函数内部,局部变量 year 的值为 2077,它与全局变量 year 互不影响。在 main() 函数中,访问的仍然是全局变量 year。

extern 关键字

如果一个全局变量在一个源文件中定义,而需要在另一个源文件中使用,此时可以使用 extern 关键字在使用的源文件中声明该全局变量。这告诉编译器该变量已经在其他地方定义过了。

在当前项目的根目录中有 2 个文件:utils.c 和 main.c,整个项目结构如下图所示。

C extern 的项目结构

其中,utils.c 代码如下:

// 定义全局变量
int year = 2030;

示例 6:使用 extern 关键字(main.c)

#include <stdio.h>

// 声明在 utils.c 中定义的全局变量
extern int year;

int main(void)
{
    printf("%d", year);
    return 0;
}

然后我们需要使用 gcc 同时编译 main.c 和 utils.c,也就是在 VSCode 中先执行 “gcc main.c utils.c -o output”,然后再运行 “./output”,其结果如下。

2030

最后来总结一下,在使用全局变量和局部变量时,小伙伴们要注意以下几点:

  • 尽量减少全局变量的使用:过多地使用全局变量可能会导致程序的可维护性降低,因为全局变量可以在程序的任何地方被修改,这使得跟踪变量的变化变得困难,并且容易产生意想不到的副作用。
  • 局部变量优先:在能够满足需求的情况下,应该优先使用局部变量。因为局部变量的作用域仅限于函数内部,有助于提高代码的模块性和独立性。
  • 注意变量的初始化:在使用变量之前务必对其进行初始化,特别是局部变量,这样可以避免使用未定义的值。全局变量通常会被默认初始化,但显式初始化可以提高代码的可读性。
  • 避免全局变量与局部变量同名:虽然 C 语言允许全局变量和局部变量同名,但这会降低代码的可读性,容易引起混淆。我们应该尽量避免这种情况,或者使用清晰的命名约定来区分它们。

上一篇: C 函数参数

下一篇: C void 类型

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号