阅读C primer plus第十二章记录—— 多文件C程序(包含概念:存储类别、链接和翻译单元、extern关键字)

由于学习C语言时仅仅学习单文件C程序,工作中发现工程中的C代码都是多文件组织而成的,发现自己看不懂= =,来补补课,此处都是《C primer plus》内容复制和总结。

一、内存用于存储程序中的数据,由存储期、作用域和链接表征。

1.存储期可以是静态的、自动的和动态分配的。

如果是静态存储期,在程序开始执行时分配内存,并在程序运行时都存在。如果是自动存储期,在程序进入变量定义所在块时分配变量的内存,在程序离开块时释放内存。如果是动态分配存储期,在调用malloc()(或相关函数)时分配内存,在调用free()函数时释放内存。

2.作用域决定程序的那些部分可以访问某数据。

定义在所有函数之外的变量具有文件作用域,对位于该变量声明之后的所有函数可见。定义在块或作为函数形参内的变量具有块作用域,只对该块以及包含的嵌套块可见。

3.链接描述定义在程序某翻译单元中的变量可被链接的程度。

C对象有3中链接属性:外部链接、内部链接或无链接。

3.1 无链接

具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。这意味着这些变量是块私有的。

3.2 外部链接

具有文件作用域的变量可以是外部链接或内部链接。外部链接变量可以在多文件程序中使用。

3.3 内部链接

具有文件作用域的变量可以是外部链接或内部链接。内部链接变量只能在一个翻译单元中使用。

注意:正式术语和非正式术语
C标准用“内部链接的文件作用域”描述仅限于一个翻译单元(即一个源代码文件和它所包含的头文件)的作用域,用“外部链接的文件作用域”描述可延伸至其他翻译单元的作用域。但是,对程序员而言,这些术语太长了,一些程序员把“内部链接的文件作用域”简称为文件作用域,把“外部连接的文件作用域”简称为|“全局作用域”或“程序作用域”。
(PS:觉得非正式简称更加形象)

int giants = 5;               //外部链接的文件作用域,非正式简称:程序作用域,全局作用域
static int dodgers = 3;		  //内部链接的文件作用域,非正式简称:文件作用域
int main()
{
	...
}

翻译单元和文件
翻译单元也称编译单元,每个翻译单元均对应一个源代码文件和它所包含的文件。
错误认识:一个.c文件即是一个翻译单元。
实际上,你认为的多个文件在编译器中可能以一个文件出现,例如,通常在源代码(.c扩展名)中包含一个或多个头文件(.h扩展名)。头文件会依次包含其他头文件,所以会包含多个单独的物理文件。但是,C预处理实际上是用包含的头文件内容替换#include指令。
所以,编译器将源代码文件和所有的头文件都看成是一个包含信息的单独文件,这个文件被称为翻译单元(translation unit)。描述一个具有文件作用域的变量时,它的实际可见范围是整个翻译单元。

作用域和链接描述了标识符的可见性。

二 、C的五种存储类别

下面是C的五种存储类别(不包括线程的概念):

1. 自动

在块中不带存储类别说明符或带auto存储类别说明符的变量属于自动存储类别,具有自动存储期、块作用域、无链接。如果未初始化自动变量,它的值是未定义的。(举例:在函数内定义的局部变量)

2. 寄存器

在块中带register存储类别说明符声明的变量(或作为函数头的形参)属于寄存器存储类别,具有自动存储期,块作用域、无链接,且无法获取其地址。把一个变量声明为寄存器变量即请求编译器将其存放到访问速度最快的区域,如果未初始化寄存器变量,它的字节都被设置为0.

3. 静态、无链接

在块中带static存储类别说明符声明的变量属于“静态、无链接”存储类别,具有静态存储期、块作用域、无链接。只在编译时被初始化一次,如果未显式初始化,它的字节都被设置为0.

4. 静态、外部链接

在所有函数外部且没有使用static存储类别说明符声明的变量属于“静态、外部链接”存储类别,具有静态存储期,文件作用域,外部链接。只能在编译时被初始化一次,如果未显式初始化,则它的字节都被设置为0.

5. 静态、内部链接

在所有函数外部且使用了圣拓陶瓷存储类别说明符声明的变量属于"静态、内部链接"存储类别,具有静态存储期、文件作用域、内部链接。只能在编译时被初始化一次。如果未显式初始化,它的字节都被设置为0.

三、extern关键字的说明

extern 关键字用来声明变量或函数,extern表明该声明不是定义,表明该变量或函数定义在别的文件中,它指示编译器去别处查询其定义,不要用关键字extern创建外部定义,只用它来引用现有的外部定义。(简言之:不能用extern给变量赋值,只能声明引用)
注意,如果外部变量定义在一个文件中,那么其他文件在使用该变量之前必须先声明它(用extern关键字)。也就是说,在某文件对外部变量进行定义式声明只是单方面允许其他文件使用该变量,其他文件在用extern声明前不能直接使用它。(简言之:不使用extern声明,就不让你用这个变量)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值