代码背后的故事

我们通常只是注意到代码的外部表现,却很少关注代码背后的故事。下边我来简述代码背

后的故事。

在vc++6.0环境下,当我们写好一段代码,点编译,进而链接,然后执行,如果各步都无

错,就可以显示程序的输出结果。

在gcc下,直接gcc +要编译的源文件名,就可编译程序,./a.out就可以打印出结果。

其实上述的过程都是分四个阶段执行的。

  第一阶段:预编译阶段:引入头文件,去除注释,define定义的标识符的替换,宏的替

换。

define定义的标识符是没有参数的,而宏是有参数的。

在gcc下,用gcc 文件名 -E就可以显示预编译后的结果。此时我们可以看到头文件被引入

了,注释也被取消了(换成空格)。这个过程大家可以在自己的环境下进行尝试,这里就

不给出截图了。

第二阶段:编译。在gcc下,用gcc 文件名 -S就可以显示编译后的结果。这个阶段又分

四个步骤进行完成。

  (1)词法分析:词法分析主要分析源程序中的字符流能否构成正确的单词。

词法分析的功能可以表示为:

     源程序------>词法分析程序------>token串

它是编译器中唯一与源程序打交道的部分,主要工作如下:

   a.按照构词规则识别单词,输出单词本身及其种别码。(种别码表示单词的种类,通

常用整形编码表示)。

   b.滤掉源程序中的无用成分,如注释,空格,回车换行等。

   c.调用出错处理程序,识别并定位错误。

   d.调用符号管理程序,对识别出来的单词及其属性进行管理。

  (2)语法分析:是对高级语言的句子结构进行分析,是编译过程的核心。它的任务是

识别输入的单词序列是否符合语言的语法规则,如果符合就生成语法树。

语法分析的功能可以表示为:

   token串----->语法分析程序------>语法树

语法分析主要是对能否按照正确语法构成单词进行检查。

语法分析是有多种方法,感兴趣的读者可以自行阅读。

  (3)语义分析:对每个语法结构进行静态语义检查,即检查名字是否定义,类型是否

合理等等。

  (4)符号表汇总:生成中间代码。

符号表是一种数据结构,用于保存源程序中出现的名字及其相关的属性信息。在《数

组,指针》这篇文章中提到:编译器通常不会为普通const只读变量分配内存,而是将他

们保存在符号表中。符号表要在编译的多个阶段中进行操作。在词法分析阶段,只有单

词的名字和长度等内容可以写进符号表,关键字并不写入符号表。在语义分析阶段,发

现语义正确,就将单词的类型写入符号表。比如:

代码中的一行语句:

int  i , j, k;
在词法分析阶段,int是关键字,不会被写入符号表,i,j,k都会被写入,长度都是1,在语

义分析阶段和符号表汇总阶段,判断出i,j,k都是标识符,int是三个变量的类型,所以将

类型写入符号表。

第三阶段:汇编,生成可重定位的目标文件(.o文件),已将文件分段,形成符号表。

由于汇编语言具有管理不同名字的存储分配功能,所以在生成汇编代码后需要扫描符号

表,并对变量分配空间。在gcc下,用gcc 文件名 -C就可以显示汇编后的结果。

前三个阶段被称为编译阶段,生成目标文件。

第四阶段:链接,在gcc下,用gcc 文件名 -o就可以显示链接后的结果。在此阶段完成

段表的合并,符号表的合并和符号表的重定位(重名符号地址不同,找出有效地址)。

符号表的合并是指:一个工程中可能有多个源文件,所以就会生成多个符号表,所以将

这些符号表合并起来,windows下生成.exe文件,linux下生成a.out文件。

在vs下,生成的符号表都被存放在pdb文件中。我打开这个文件,都是二进制数据,大

家可以打开看看。



上文参考书籍:《编译原理及实践教程》(第2版)(黄贤英著)

文章可能会有不合理的地方,希望读者指出~~谢谢

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值