首页 > 图书中心 >图书详情

C编译器剖析

学习用C语言设计自己的编译器。

作者:邹昌伟
定价:49
印次:1-1
ISBN:9787302426103
出版日期:2016.06.01
印刷日期:2016.05.18

“编译原理”课程是一门理论性与实践性非常强的课程,应遵循从具体到抽象的认知规律。本书以一个开源的C编译器(UCC)为案例,在源代码分析的过程中,展开对编译原理相关知识的学习和讨论。全书共分6章: 第1章介绍文法和递归等知识点,并采用结合C语言的方式来讨论汇编代码;第2章讨论UCC编译器的词法分析、内存管理、符号表管理和类型系统等基本模块;第3章介绍UCC编译器的语法分析,采用的是手工打造分析器的技术路线;第4章介绍语义检查,通过本章的学习,有助于C程序员站在编译器的角度来深入理解C语言的语义规则;第5章分析UCC编译器的中间代码生成及优化;第6章介绍如何生成32位的x86汇编代码。 本书不仅是很好的编译原理和编译器设计教材,也可作为读者深入学习C程序设计的参考用书。

more >

01我是在大三的时候开始学习“编译原理”课程的,授课的是陈意云老师,使用的是陈老师自己编写的教材。这本教材理论知识非常丰富,每章后面有不少颇有难度的练习题。非常感谢陈老师讲的这门课程,我有限的编译原理理论知识基本上是从这门课程学的。但学完之后,总有一个感觉,即自己掌握的知识比较分散,不能完整地把它串起来。与国内其他高校差不多,这门课的大作业是一个玩具语言的编译器实现,之所以说是玩具语言,是因为语言本身很简单,缺乏很多实用的特性,无法作为实际的编程语言使用。当时就有一个模糊的想法,想自己写一个实用编程语言的编译器,这个编译器不能复杂,得适合在一个学期的时间中学习和掌握,但一直停留在想法这个阶段,也没想好实现哪个语言。 我在后来的学习和工作中一直和系统编程打交道,使用的基本上是C语言。对C语言的一些精巧特性也越来越熟悉,比如说“为什么函数标准的入栈顺序是从右到左”和“setjmp/longjmp是如何实现的”等。C语言的使用非常广泛,而且以精练著称,如果能写一个C编译器就很好了。开源的GCC非常复杂,基本上不适合学习。其间我完整地阅读了LCC的源代码,LCC功能完整,代码精简。但是LCC代码本身比较难懂,结构不清晰。我在这个时候就明确下来写一个适合学习的C编译器,这个编译器得有如下几个要点: (1) 用C语言来实现C编译器,一是因为我最熟悉的是C语言,二是能实现自举(bootstrap),这是对编译器很好的测试。 (2) 代码简洁易懂,结构清晰,适合学生学习和掌握。 (3) 实现ANSI C89标准。 (4) 一定要开源,因为我在学习和工作中受到开源社区的帮助很大。 (5) 编译器的核心难点和复杂度在后端优化,这是一个简单的用来学习基本原理的编译器,基本不涉及后端优化。 我从2007年开始在闲暇时间构思编写UCC,即Your C Compiler的缩写,断断续续用了一年半的时间完成。完成后我很开心,第一时间将其开源在sourceforge网站上,后来因为各种缘故,开源后一直没有维护。 现在非常高兴地看到邹老师以UCC编译器源码为基础,写了这本理论结合实践的书。这本书不是简单的源码剖析,它以编译原理的理论作为主线把整个知识串起来,辅以实际代码的讲解。我相信这种方式对于在校学生或者编译器爱好者非常有帮助。可能绝大部分程序员在职业生涯中不需要〖1〗C编译器剖析序[3]〖3〗去写一个完整的编译器,但是编译器的一些理论和算法在很多领域得到使用,掌握了编译原理的基础知识之后,会对代码的优化和效率有更好的理解,而且容易掌握一些比较难的语言特性,比如说LISP语言中的闭包和continuation等概念。 语言是对计算机硬件特性本身的一个抽象,汇编语言抽象的层次低,C语言抽象的层次高。整个编译器的轴心就是如何把一个高阶的抽象逐渐变成一个低阶的抽象。这个过程不是一步到位的,是经过了词法分析、语法分析和语义分析等步骤逐渐完成的。每一步可以看作是把一个高阶的抽象语言变成一个稍低阶的抽象语言。带着这样一个主线去学习邹老师的这本书和UCC源代码,相信大家能很好地掌握编译原理。 小米公司MIUI首席架构师、UCC编译器作者 汪文俊 自从1999年在Turbo C 2.0下第一次用C语言写出Hello World以来,不知不觉在IT相关行当里混了近16年了。相信所有上机写过Hello World的人当初都会有这样的好奇心:由键盘敲进去的不过是一个个普通的英文字符,C编译器是如何神奇地发现哪一行出现了什么样的语法错误,更神奇的是编译连接后的可执行程序又是怎样在操作系统上运行起来的?这些问题也一直萦绕在我脑海里,挥之不去。大学时所学的“操作系统”和“编译原理”课程似乎对这些问题给出了答案,似乎又没有。很遗憾,那时也没有人告诉我,想比较彻底地搞明白这些问题,最好的办法是去读编译器或操作系统的源代码。因为“计算机科学与技术”这一学科虽然冠上了“科学与技术”之名,但实际上还是“技术”的成分要来得多些。在所有强调“技术”的工作中,“技术”通常只能来源于长期的动手实践。即便是开车倒库这样的操作也是个技术活,没有长期动手实践是倒不好车的。纸上得来终觉浅,绝知此事要躬行。而不少牛人在大学里上完“操作系统”和“编译原理”课程后就已脱颖而出,比如大牛Linus和Chris Lattner,前者大学时就建立了他的Linux操作系统王国,而后者也在研究生期间缔造了如今在业界如日中天的LLVM编译器。Apple公司已经不动声色地把公司的ObjectC编译器从GCC转成了LLVM和Clang,各位的iPhone手机中运行的代码可能正是LLVM和Clang的产物呢。Apple公司新推出的Swift语言背后站着的仍然是Charis Lattner和LLVM。 能写出工业水准的操作系统和编译器的人绝对是大牛,而写出来的操作系统和编译器能被工业界普遍接受,则需要命运和机遇的垂青。大部分程序员注定是成为高级或低级的“码农”,成为软件生产流水线上的一颗螺丝钉。在生活和工作的压力面前,我们往往习惯于不做那么深入思考,只要代码能实现需求就可以,至于“为什么”的问题,人们往往有意或无意甚至被迫地将之忽略。就如儿时的梦想,只有在夜深人静时,想着年华已去,看着岁月无情,捧着那泛黄的旧照片时,才发现一直以来自己内心不常去的角落中始终留着那个梦想。 操作系统和编译器就如武侠小说中的“九阴真经”,没看过“九阴真经”的侠客也可以行走江湖,但看过并练成九阴真经的人最终才更有机会登上华山之巅。我们很幸运能生活在互联网时代,不必如20世纪七八十年代的欧美程序员那样为了一睹UNIX操作系统源代码的风采,私下偷偷复印那本〖1〗C编译器剖析前言[3]〖3〗后来被称为旷世奇书的《莱昂氏UNIX源代码分析》。其实,真正旷世之作的是那本书中分析的UNIX操作系统和用来写UNIX的C语言。当然,我们更不必为了一睹“九阴真经”而在江湖中掀起血雨腥风。因为九阴真经就摆在我们的面前——GCC、LLVM和Linux源代码就毫无保留地躺在那儿。冲动的我们一定曾经兴奋地下载了这些源代码,但面对这些动辄几百万行的源代码时,才发现自己是多么渺小和无力。其实再复杂的系统,其最初的原型往往也并不复杂,就如早期的UNIX操作系统和C编译器,而这些原型往往就是最精髓的部分,包括了最初的直觉和创意。与其面对几百万行的源代码感叹自己“too young, too simple”,不如选择一本浓缩的“九阴真经”。很幸运,只要我们打开Google搜索,就能找到这些原型版的操作系统和编译器。 如果要分析的是开源的、相对完整的C编译器源代码,而不是一个教学用的玩具,并且希望源代码的行数在一万行左右,那Google给我们的答案中就有这么两个,一个是LCC编译器,另一个是UCC编译器。如果我们还希望代码结构清晰,且函数名等能见名知义,能直接与C语言的文法吻合,不必去猜测这个函数名是哪几个单词的缩写,那UCC会更胜一筹。但很遗憾,UCC的原作者汪文俊(wenjunw123@gmail.com)没有写关于UCC的书,他其实是最合适的人选。于是,UCC就如一颗被遗落在角落的珍珠,渐渐地蒙上了尘埃。一万行左右的代码量,UCC就能实现一个基本完整的C编译器,虽然其后端只面向32位的x86平台,也没有如LCC那样的可变目标——既可生成MIPS,也可生成SPARC和x86代码。尽管偶有缺陷,纵然碧玉有瑕,即便不够知名,但只要把UCC这只麻雀解剖清楚,就能搞清C编译器是如何工作的,能站在编译器实现的角度来品味经40余年而历久弥新的C语言。C和C++语言的相关书籍中,最经典的有The C Programming Language、C++ Primer和The C++ programming language,之所以经典,很大原因是这些作者本身就是C或C++编译器的最早期实现者。 越俎代庖去写关于UCC编译器的书,希望这本书能帮助有兴趣读它的人基本搞明白C编译器,用好C语言这个简洁有力的利器。当然,正如一位在编译一线战斗的朋友所言,“UCC和LCC还停留在编译前端和后端的初级阶段”,编译器的优化是现在工业界更加关注的焦点,UCC和LCC在后端优化上都做得不够。不过,站在广大C程序员的角度来看,C编译器的前端才是C编译器与程序员的接口,理解了C编译器前端的实现,就能更深刻地理解C语言的语法和语义;而C编译器后端其实是C编译器与CPU的接口,后端优化的目标往往是在保持语义的前提下生成速度更快的机器代码。我不是什么牛人,只希望这本书能帮有心人开启一扇看得见、够得着的编译大门,让C程序员能站在编译器实现的角度来看看自己朝夕相伴的C语言。全国每年有十万名以上的计算机相关专业学生毕业,“编译原理”课程在大多数毕业生中留下的印象就是很难及很理论化。本书的目的是想把“编译原理”课程具体化,所谓“伤其十指,不如断其一指”。如果你熟悉C语言,并且有基本的数据结构的知识,那就和我们一起开启C编译器剖析这趟旅程,学习编译原理和汇编语言相关的知识,期盼这趟行程结束后,不论你的下一站去何方,你都能觉得不虚此行。众里寻她千百度,蓦然回首,这就是C编译器。那我们就启程吧! 衷心感谢文俊兄在百忙中为本书写的序。从UCC编译器的源代码中,我受益颇多。在UCC源代码的阅读、分析和修改过程中所感受的快乐,像无形的指挥棒驱使着我把其中的心得和体会写在博客http://blog.csdn.net/sheisc上。非常感谢清华大学出版社提供的出版机会,十分感谢本书的责任编辑龙启铭老师在本书出版过程中提供的帮助和指导。作为一名在教育一线工作的普通教师,我诚挚地希望拙作能传递这份快乐和收获,能为想深入理解UCC编译器的朋友们提供一点帮助。书中难免会有不足之处,敬请读者给予批评指正。

more >
扫描二维码
下载APP了解更多

同系列产品more >

网页设计与制作(第4版)

赵旭霞,刘素转,刘文胜
定 价:49元

查看详情
人工智能基础

陈明
定 价:69元

查看详情
深度学习算法与实践

郝晓莉,王昌利,侯亚丽
定 价:59元

查看详情
算法设计与分析

张树东,罗宁,柳昊明
定 价:49元

查看详情
高性能计算机体系结构

刘超 主编 江爱文,
定 价:49元

查看详情
图书分类全部图书
more >
  • 1)用C语言实现C编译器。

    2)代码简洁易懂,结构清晰。

    3)遵循ANSI C89标准。

    4)本书以一个开源的C编译器(UCC)为案例,在源代码分析的过程中,展开对编译原理相关知识的学习和讨论。

    5)很好的编译原理和编译器设计教材,也是深入学习C程序设计的参考用书。

     

more >
  • 第1章基础知识/1

    1.1语言、文法与递归1

    1.2一个较复杂的文法4

    1.3由文法到分析器7

    1.3.1表达式7

    1.3.2声明15

    1.3.3语句21

    1.4UCC编译器预览28

    1.4.1UCC的使用28

    1.4.2UCC驱动器31

    1.5结合C语言来学汇编35

    1.5.1汇编语言简介35

    1.5.2整数运算42

    1.5.3浮点数的算术运算48

    1.5.4浮点数之间的比较操作51

    1.5.5指针、数组和结构体53

    1.6C语言的变量名、数组名和函数名55

    1.7C语言的变参函数58

    1.8本章习题65

     第2章UCC编译器的基本模块/66

    2.1从Makefile走起66

    2.2词法分析69

    2.3UCC编译器的内存管理74

    2.4C语言的类型系统81

    2.5UCC编译器的符号表管理91

    2.6本章习题100

    第3章语法分析/101

    3.1C语言的表达式101〖1〗C编译器剖析目录[3]〖3〗3.1.1条件表达式和二元表达式101

    3.1.2一元表达式、后缀表达式和基本表达式111

    3.2C语言的语句122

    3.3C语言的外部声明131

    3.3.1声明和函数定义131

    3.3.2与声明有关的几个非终结符142

    3.3.3声明说明符和声明符147

    3.4本章习题166

    第4章语义检查/167

    4.1语义检查简介167

    4.2表达式的语义检查168

    4.2.1表达式的语义检查简介168

    4.2.2数组索引的语义检查173

    4.2.3基本表达式的语义检查179

    4.2.4函数调用的语义检查184 ...

精彩书评more >

标题

评论

版权所有(C)2023 清华大学出版社有限公司 京ICP备10035462号 京公网安备11010802042911号

联系我们 | 网站地图 | 法律声明 | 友情链接 | 盗版举报 | 人才招聘