Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1708865
  • 博文数量: 98
  • 博客积分: 667
  • 博客等级: 上士
  • 技术积分: 1631
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-27 15:59
个人简介

一沙一世界 一树一菩提

文章分类

全部博文(98)

文章存档

2021年(8)

2020年(16)

2019年(8)

2017年(1)

2016年(11)

2015年(17)

2014年(9)

2013年(4)

2012年(19)

2011年(1)

2009年(4)

分类: C/C++

2015-08-19 10:19:20

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

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

下面听我一一道来。

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

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

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

阅读(1960) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~