从链接的角度理解C语言的static和extern

背景

static和extern是C的关键字之一,最近阅读《C和指针》的时候发现自己先前的理解非常浅薄,因此将书中内容进行梳理和总结,希望更多人能有所收获。

链接属性

为了更好得理解这两个关键字,这里要先引入一个概念,即编译属性。从源码到可执行文件需要经过编译,编译的其中一步就是链接。

在C语言种,任何声明的标识符(函数名,变量)都有一个编译属性。该属性决定了在链接过程中,编译器如何去处理这些标识符,一共三种编译属性。

None        独立个体,可重复声明,不互相影响
internal单文件内部唯一,不可重复声明
external全局唯一,不可重复声明

为了更好得理解这三种属性,这里再详细得举例说明每种属性的标识符常见形式

None属性标识符

局部变量

局部变量名仅在该变量有效的一小块代码段有效,函数外、文件外,均可以有同名变量

函数入参

函数的入参仅在函数内有效,函数外,文件外,均可有同名变量

external属性标识符

全局变量

在文件外声明的变量就是全局变量,全局变量在所有文件内唯一,这里做一个实验

在文件main.c内声明 int a;在文件test.c内声明int a;使用GCC进行编译

编译器提示重复定义

函数的实现 

这个很好理解,如果你有两个同名的函数实现,那么当调用它的时候,程序就无法知道该函数的入口地址究竟是哪了

internal属性标识符

static修饰的全局变量/函数实现

在这里首次出现了static关键词,这就是他的作用之一,将external属性的标识符变为internal;这样有什么用呢?

答案就是,在不同文件中,你可以使用同名的全局变量、函数实现,现在仅需要保证在同一文件中,这两类标识符是唯一的就可以了。

上面的例子中,我们将其中一个文件的int a变为static,看看会发生什么

这里给两个文件中的a赋了不同的值,编译没有问题,打印也证明了,在各自的文件内使用了各自的value,小范围的变量总是高于大范围同名变量的

存储方式

最后简单补充一下各类标识符的存储位置,就能对extern和static的作用进行总结了

程序中的标识符一般有两种存储方式:

1.静态存储,在编译阶段已经分配好内存空间

常见的静态存储的有:全局变量,函数实现等

2.动态存储,通过堆栈的方式在代码运行阶段动态存储,地址是不确定的

动态存储的有:局部变量,函数入参等

当然,实际编译中还会将其划分之代码段和数据段,这里不做展开

静态存储的数据,在编译时就已有确定的值,同时因为他存放的位置是静态的,不会因为函数调用等进行堆栈释放的操作而丢失值。譬如一个全局变量,如果你的多个函数都会用到它,那么他们的结果是会相互影响的

动态存储的数据,其实就是堆栈中的数据,当你调用函数时,程序申请一块内存来用于函数中局部变量,入参等值的保存,当函数结束后,这块申请的内存是会出栈的,那么这些局部变量也就被释放了

static和extern

有了以上的background后,就可以很清晰得对这两个关键字进行说明了

static

-存储方式:将变量放至静态存储区域,不会因为栈的释放而丢失值

-链接属性:将external属性的标识符变为internal

extern

extern不影响存储属性,同时,他也是一种默认的状态。

什么意思呢?

对于全局变量来说,他本身就是external的链接属性,不需要再手动去修饰他

那extern究竟能用于什么场景,这里我总结了两点:

1.将文件外的标识符作用域扩展至该声明的作用范围

举个例子:

在test.c中有一个全局变量a,我在main.c中也想访问他,直接访问肯定是不行的,这时候我需要在main.c中声明 extern int a;这样,两个文件就能访问同一个a了

2.该关键字是一种良好的编程习惯

举个例子,一般来说,我们把功能写在单独的.c文件中,在main.c中通过头文件引入所有的函数声明,假如没有头文件,你又想使用文件外的函数,直接写一个他的声明是没有问题的

但倘若你使用

extern void test_func(void);

那么给读者一种很明确的信息,这个函数的定义是在文件外的,而非该文件内,这是一种很好的编程实践

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值