说说C语言声明、定义和编译的关系

这几天,晚上看看《linux多线程服务器端编程》,看到C语言关于编译的部分,感觉说的挺细,所以特意记下。
这部分内容的标题是:C语言的编译模型,书中说的比较细,自己只是把一些点记下,作为自己的读书笔记而已,所以没有用原书的标题。

C语言里为什么函数要先声明在定义呢?
外部变量为什么要先声明呢?
为什么结构体就必须先定义呢?

下面听我一一道来。

C语言的编译分为四个步骤:预处理、编译、汇编、链接。是按照“单遍编译”来设计的,所谓单边编译,指的是从头到尾扫描一遍代码,一边解析代码,一边即刻生成目标代码。在单遍编译的时,编译器只能看见当前语句/符号之前已经解析过的代码,看不到之后的代码,这就有了下面的结论:

1 结构体必须先定义,才能访问其成员,否则编译器不知道结构体成员的类型和偏移量,就无法立刻生成目标代码。
2 局部变量也必须先定义再使用,因为如果把定义放在后面,编译器在第一次看到一个局部变量时不知道它的类型,也不知道它在stack里的位置,也不知道占多少satck空间,也就无法即刻生成目标代码。
3 对于外部变量,编译器只需要知道它的类型和名字,不需要知道它的具体地址,因此这里其实需要的只是一个声明,在生成的目标代码中,外部变量的地址空着,留给链接器去填。
4 当编译器看见函数调用时,先找函数声明,编译器可以立刻生成调用函数的汇编代码(参数,名字,返回值),这里唯一尚不能确定的是函数的实际地址,编译器就留下一个空白给链接器去填。

可见,对于C编译器来说,只需要记住struct的成员和偏移量,知道外部变量的类型,就足以一边解析源代码,一边生成目标代码。外部符号(函数或者变量)的决议(resolution)可以留给链接器去做。也因此,大家看见有的函数声明中参数只有类型,没有具体名字,并且为了减少头文件依赖,现在的C源文件也尽量使用前向声明。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值