C语言:静态全局变量为什么能在外部访问?

文章通过例子解释了全局变量与静态全局变量在C语言中的不同行为。全局变量通常可以在外部通过extern声明访问,而静态全局变量则限制了其作用域,不允许外部访问。文章强调了‘外部’的含义是指单独编译的模块外部,并通过编译和链接过程展示了这一概念。通过示例代码,演示了正确引用全局变量和静态全局变量的方法,以及未正确引用静态全局变量时会出现的链接错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们在学习全局变量的时候,常说全局变量可以在外部访问,只要在外部加上extern关键字声明,即可使用,而如果这个全局变量加上了static关键字修饰,即变成了【静态全局变量】的时候,外部则无法访问了,但很多人在尝试的时候会发现,外部竟然也可以访问,甚至不加extern关键字都能访问到。

原因是:使用了不正确include,并理解错了“外部”的含义。

下面以linux环境举例说明,假设两个文件v1.c和v2.c,v2.c中包含一个全局变量a,v1中使用extern关键字使用这个a,应该写如下代码:

// v1.c
#include <stdio.h>

int main() {
    extern int a;
    printf("extern int a = %d\n", a);

    return 0;
}
// v2.c
#include <stdio.h>

int a = 100;
static int b = 101;

如果在v1.c中写了#include "v2.c",那么v2.c会被当成v1.c的一部分,此时虽不在同一个源文件中,但二者仍像在同一个文件中一样,是不能称为“外部”的。必须像如上这种不存在直接include关系的情形,才能称为“外部”。但以上代码如何编译并运行?此处使用gcc来操作:

gcc -c v1.c v2.c              # 编译产生v1.o v2.o
gcc v1.o v2.o -o vmain        # 将v1.o和v2.o经过链接成可执行文件vmain

./vmain    # 执行vmain

执行后得到结果:

[yancy@localhost test]$ gcc -c v1.c v2.c
[yancy@localhost test]$ gcc v1.c v2.c -o vmain
[yancy@localhost test]$ ./vmain
extern int a = 100
[yancy@localhost test]$ 

以上才是正确的引用外部全局变量的方法。

而用这种方法,在v1.c中引用v2.c中定义的static全局变量:

#include <stdio.h>

int main() {
    extern int a;    // 引用外部的全局变量a
    printf("extern int a = %d\n", a);

    extern int b;    // 试图引用外部的静态全局变量b
    printf("extern int b = %d\n", b);

    return 0;
}

则会在链接环节报错:

[yancy@localhost test]$ gcc -c v1.c v2.c
[yancy@localhost test]$ gcc v1.c v2.c -o vmain
/tmp/ccGRMlxv.o: In function `main':
v1.c:(.text+0x1d): undefined reference to `b'
collect2: error: ld returned 1 exit status
[yancy@localhost test]$ 

这也证实了,static全局变量无法在外部被使用。

这里的【外部】,实际上是【单独编译的模块外部】,就是这里gcc -c形成的.o文件,每一个.o文件是一个单独的模块,所以不能以【源文件】外部为准,是站在编译角度来说的。当初刚学C语言的时候,并不理解编译、链接等内容,导致这个问题一直没懂,希望这里能帮大家解惑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值