标题：LinuxC编程一站式学习
图书信息
作者：北京亚嵌教育研究中心   宋劲杉 编著
出版社：电子工业出版社
ISBN：978-7-121-09771-3
出版日期：2009年11月
定价：60.00元
开本：16开
页码：480页
适用人群
本书适合做零基础的初学者学习C语言的第一本教材，帮助读者打下牢固的基础。有一定的编程经验但知识体系不够完整的读者也可以对照本书查缺补漏，从而更深入地理解程序的工作原理。本书最初是为北京亚嵌教育研究中心的嵌入式Linux系统工程师就业班课程量身定做的教材之一，也适合作为高等院校程序设计基础课程的教材。本书对于C语言的语法介绍得非常全面，对C99标准做了很多解读，因此也可以作为一本精简的C语言语法参考书。
前 言
本书最初是为北京亚嵌教育研究中心的嵌入式Linux系统工程师就业班课程量身定做的教材之一。该课程是为期四个月的全日制职业培训，要求学员毕业时具备非常Solid的C语言编程能力，能熟练地使用Linux系统，同时对计算机体系结构与指令集、操作系统原理和设备驱动程序都有比较深入的了解。然而学员入学时的水平是非常初级而且参差不齐的：学历有专科、本科也有研究生；专业有和计算机相关的，也有很不相关的（例如会计专业）；以前从事的职业有和技术相关的也有完全不相关的（例如HR）；年龄从二十岁出头到三十五六岁的都有。这么多背景、基础、思维习惯和理解能力完全不同的人来听同一堂课，大家都迫切希望学会嵌入式开发技术，投身IT行业，这就是职业教育的特点，也是我编写本书时需要考虑的主要问题。
学习编程绝不是一件简单的事，尤其是对于零基础的初学者来说。大学的计算机专业有四年时间从零基础开始培养一个人，微积分、线性代数、概率论、离散数学、组合数学、自动机、编译原理、操作系统、计算机组成原理等一堆基础课，再加上C/C++、Java、数据库、网络工程、软件工程、计算机图形学等一堆专业课，最后培养出一个能找到工作的学生。很遗憾这最后一条很多学校没有做好，据我们考查，来亚嵌培训的很多学生基础几乎为零，我不知道为什么。与之形成鲜明对比的是，只给我们四个月的时间，同样要求从零基础开始，最后培养出一个能找到工作的学生，而且还要保证他找到好工作，这就是职业教育的特点。
为什么我说“只给我们四个月的时间”？我们倒是想教四年呢，但学时的长短我们做不了主，是由市场规律决定的。四年的任务要求四个月做好，要怎么完成这样一个几乎不可能的任务呢？有些职业教育给出的答案是“实用主义”，打出了“有用就学，没有用就不学”的口号，大肆贬低说大学里教的基础课都是过时的、无用的，只有他们教的技术才是实用的。这种炒作很不好，我认为大学里教的每一门课都是非常有用的，基础知识在任何时候都不会过时，倒是那些时髦的“实用技术”有可能很快就会过时了。
四年的任务怎么才能用四个月做好？我们给出的答案是“优化”。现在大学里安排的课程体系最大的缺点就是根本不考虑优化。每个过来人都会有这样的感觉：大一大二学了好多数学课，却不知道都是干什么用的，不明白为什么要学。连它有什么用都不知道怎么能有兴趣学好呢？到大三大四学专业课时，用到以前的知识了，才发现以前学的数学是多么有用，然而早就忘得一干二净了，考完试都还给老师了。回头重新学，才发现很多东西以前根本没学明白，现在真的学明白了，那么前两年的时间岂不是都浪费了？大学里的课程体系还有一个缺点就是不灵活，每门课必须占用一个学期，必须由一个老师教，不同课程的老师之间没有任何沟通和衔接，其实这些课程之间是相互依赖的，把它们强行拆开是不符合人的认知规律的。比如我刚上大学的时候，大一上半学期就被逼着学习C语言，其实C语言是一门很难的编程语言，不懂编译原理、操作系统和计算机体系结构根本不可能学明白，那半个学期自然就浪费掉了。当时几乎所有学校的计算机相关专业都是这样，大一刚来就学C语言，有的学校更疯狂，上来就学C++，导致大多数学生都以为自己会C语言，但其实都是半吊子水平，到真正写代码的时候经常为一个Bug搞得焦头烂额，却没有机会再系统地学一遍C语言。因为在学校看来，C语言早在大一就给你“上完了”，就像一顿饭已经吃完了，不管你吃饱没吃饱，不会再让你重吃一遍了。显而易见，如果要认真地对这些课程进行优化，的确是有很多水分可以挤的。
本书有什么特点
 本书不是孤立地讲C语言，而是和编译原理、操作系统、计算机体系结构结合起来讲。或者说，本书的内容只是以C语言为载体，真正讲的是计算机和程序的原理。
 强调基本概念和基本原理，在编排顺序上重视概念之间的依赖关系，每次引入一个新的概念，只依赖于前面章节已经讲过的概念，而绝不会依赖于后面章节要讲的概念。有些地方为了叙述得完整，也会引用后面要讲的内容，比如说“有关××我们到第×章再仔细讲解”，凡是这种引用都不是必要的依赖，可以当它不存在，只管继续往下学习就行了。
 尽量做到每个知识点直到要用的时候才引入。过早引入一个知识点，讲完了又不用它，读者很快就会遗忘，这是不符合认知规律的。
本书面向什么样的读者
这是一本从零基础开始学习编程的书，不要求读者有任何编程经验，但读者至少需要具备以下素质：
 熟悉Linux系统的基本操作。如果不具备这一点，请先参考其他教材学习相关知识，熟练之后再学习本书，《鸟哥的Linux私房菜》据说是Linux系统管理和应用方面比较好的一本书。但学习本书并不需要会很多系统管理技术，只要会用基本命令、会自己安装系统和软件包就足够了。
 具有高中毕业的数学水平。本书会用到高中的数学知识。事实上，如果不具有高中毕业的数学水平，也不必考虑做程序员了。但并不是说只要具有高中毕业的数学水平就足够做程序员了，只能说看这本书应该没有问题，数学是程序员最重要的修养，计算机科学其实就是数学的一个分支，如果你的数学功底很差，日后还需要恶补一下。
 具有高中毕业的英文水平。理由同上。
 对计算机的原理和本质深感兴趣，不是为就业而学习，不是为拿高薪而学习，而是真的感兴趣，想把一切来龙去脉搞得清清楚楚而学习。
 勤于思考。本书尽最大努力理清概念之间的依赖关系，力求一站式学习，读者不需要为了找一个概念的定义去翻阅其他书籍，也不需要为了搞清楚一个概念在本书中乱翻一通，只需要从前到后按顺序学习即可。但一站式学习并不等于傻瓜式学习，有些章节有一定的难度，需要读者积极思考才能领会。本书可以替你节省时间，但不能替你思考，不要指望像看小说一样走马观花看一遍就能学会。
为什么要学这本书而不是K&R
《The C Programming Language》（后文简称[K&R]）是公认的世界上最经典的C语言教程之一，这点毫无疑问。在C标准出台之前，K&R第一版就是事实上的C标准。C89标准出台之后，K&R跟着推出了第二版，可惜此后就没有更新过了，所以不能反映C89之后C语言的发展以及最新的C99标准。本书在这方面做了很多补充。本书与其说是讲C语言，不如说是以C语言为载体讲计算机和操作系统的原理，而K&R只是为了讲C语言而讲C语言，侧重点不同，内容编排也很不相同。K&R写得非常好，代码和语言都非常简洁，但很可惜，只有会C语言的人才懂得欣赏它，K&R是非常不适合入门学习的，尤其不适合零基础的学生学习。
本书“是什么”和“不是什么”
本书包括两大部分：
 C语言入门。介绍基本的C语法，帮助没有任何编程经验的读者理解什么是程序以及怎么写程序，培养程序员的思维习惯，找到编程的感觉。前半部分改编自《How To Think Like A Computer Scientist: Learning with C++》（后文简称[ThinkCpp]）。
 C语言本质。结合计算机和操作系统的原理讲解C程序是怎么编译、链接、运行的，同时全面介绍C的语法。位运算的章节改编自林小竹老师的讲义；链表和二叉树的章节改编自朱仲涛老师的讲义；汇编语言的章节改编自《Programming from the Ground Up: An Introduction to Programming using Linux Assembly Language》（后文简称[GroundUp]），在该书的最后一章中提到，学习编程有两种Approach，一种是“Bottom Up”，一种是“Top Down”，它们各有优缺点，而我们需要将两者结合起来。所以我编写本书的思路是：第一部分Top Down；第二部分Bottom Up；第三部分可以算填补了中间的空隙，三部分全都围绕C语言展开。
这本书定位在入门级，虽然内容很多，但不是一本百科全书，除了C语言的基础知识要讲透之外其他内容都不深入，书中列出了很多参考资料，是读者进一步学习的起点。[K&R]的第1章是一个Whirlwind Tour，把全书的内容简单概括了一遍，然后再逐个深入讲解。本书也可以看作是计算机专业课程体系的一个Whirlwind Tour，学习完本书之后读者有了一个全局观，再去学习那些参考资料就应该很容易上手了。
为什么要在Linux平台上学C语言？
用Windows学C语言不好吗？
用Windows还真的是学不好C语言。C语言是一种面向底层的编程语言，要写好C程序，必须对操作系统的工作原理非常清楚，因为操作系统也是用C语言编写的，我们用C语言编写应用程序可以直接使用操作系统提供的接口。既然你选择了本书，你一定了解：Linux是一种开源的操作系统，你有任何疑问都可以从源代码和文档中找到答案，即使你看不懂源代码，也找不到文档，也很容易找个高手教你，各种邮件列表、新闻组和论坛上从来都不缺乐于助人的高手；而Windows是一种封闭的操作系统，除了微软的员工别人都看不到它的源代码，只能通过文档去猜测它的工作原理。更糟糕的是，微软向来喜欢藏着掖着，好用的功能留着自己用，而不会写到文档里公开。本书的第一部分在Linux或Windows平台上学习都可以，但第二部分和第三部分介绍了很多Linux操作系统的原理以帮助读者更深入地理解C语言，所以后两部分只能在Linux平台上学习。
Windows平台上的开发工具往往和各种集成开发环境（Integrated Development Environment，IDE）绑在一起，例如Visual Studio、Eclipse等。使用IDE确实很便捷，但IDE对于初学者绝对不是好东西。微软喜欢宣扬傻瓜式编程的理念，告诉你用鼠标拖几个控件，然后单击一个按钮就可以编译出程序来，但是真正有用的程序有哪个是这么拖出来的？很多从Windows平台入门学编程的人，编了好几年程序，还是只知道编完程序单击一个按钮就完事了，把几个源文件拖到一个项目里就可以编译到一起了，如果有更复杂的需求他们就傻眼了，因为他们脑子里只有按钮、菜单的概念，根本没有编译器、链接器、Makefile的概念，甚至连命令行都没用过，然而这些都是初学编程就应该建立起来的基本概念。另一方面，编译器、链接器和C语言的语法有着密切的关系，不了解编译器、链接器的工作原理，也不可能真正掌握C语言的语法。所以，IDE并没有帮助你学习，而是阻碍了你的学习，本来要学好C编程只要把语法和编译命令学会就行了，现在有了IDE，除了学会语法和编译命令，你还得弄清楚编译命令和IDE是怎么集成的，这才算学明白了，本来就很复杂的学习任务被IDE搞得更加复杂了。Linux用户的使用习惯从来都是以敲命令为主，以鼠标操作为辅，从学编程的第一天起就要敲命令编译程序，等到你把这些基本概念都搞清楚了，你觉得哪个IDE好用你再去用，不过到那时候你可能会更喜欢vi或emacs而不是IDE了。
体例说明
像The quick brown fox jumps over the lazy dog这样的字体在本书中是代码字体。这种字体的名称是Dejavu Sans Mono，为什么我要提倡用这种字体呢？第一，它是等宽字体，因此适合做代码字体。第二，它的1和l、0和O区分得非常清楚（我在教学中发现初学者很容易把这些字符抄错），因此它比Courier New更适合做代码字体。第三， 它是我的Linux图形终端的默认字体，采用这种字体排版可以使得看书和看屏幕的感觉很一致，希望读者在看这本书时也会有这种Dejavu（似曾相识）的感觉。
像下面这样有边线的是代码：
#! /bin/sh
VAR=1
VAR=$(($VAR+1))
echo $VAR
没有边线的是终端显示，包括输入的命令和程序运行结果，例如：
$ VAR=1
$ VAR=$(($VAR+1))
$ echo $VAR 
2
本书中统一用$表示Shell提示符。
加粗的字句表示强调。
在定义一个名词时会给出它的英文名称，例如集成开发环境（Integrated Development Environment，IDE），通过书后的索引可以找到这些定义在书中首次出现的位置。
致谢
本书的写作得到了北京亚嵌教育研究中心的全力支持，尤其感谢李明老师和何家胜老师。没有公司的支持，我不可能有时间有条件写这本书，也不可能有机会将这本书公开在网上。
然后要感谢亚嵌教育的历届学员和各位老师，在教学和讨论的过程中我经常会得到有益的启发，这些都促使本书更加完善。在本书的写作过程中，很多读者为本书提出了很有价值的建议，很多建议是热心网友通过在线评论提出的，有些网友我只知道ID或E-mail。在此向他们表示感谢。
感谢帮助过我的老师们：李明、何家胜、邸海霞、郎铁山、朱仲涛、廖文江、韩超、秦蔚、吴岳、张 、邢文鹏、何晓龙、林小竹、卫剑钒、郭同彬、王波、王磊。
感谢热心网友：ddd、wuyulei、commapopo、田伟、田雨、daidai、邓楠、杜朴风、Zoom.Quiet、陈莉君老师、杨景、章钰、chen、Jiawei Zhang、waterloo、张现超、曾宇、董俊波、RobinXiang、刘艳明、been2100、cleverd、juicerococo、徐斌、cyy、Linux_Xfce、冯海云、侯延祥、churchmice、codycody23、syfeagle、王公仆、刘敏、Laciq、yuchen、陆杨、陈杨希、love_wc3、姚磊、芝麻、wadenx、沈震、sunbingfly、mick、baaluck、曹帅军、zhoudy、朱夜光、刺猬、leezhenfeng、王兆宏、徐凯、码匠、况海斌、尹志伟、王星。
还要感谢电子工业出版社博文视点资讯有限公司的周筠老师和李冰老师的大力支持，感谢江立编辑严谨细致的工作。
在写作过程中我遇到过很多困难：工作繁忙、对未来迷茫、生活压力大、缺乏安全感、个人琐事等。然而有这么多热心的同学、老师、朋友、网友在等着阅读我的书在线更新的内容，给我提建议，希望我把书改得更完善，这是我坚持写下去的最大动力。谢谢你们！
由于作者水平十分有限，没写过C编译器和C标准库，所以疏漏之处在所难免，如有错误欢迎广大读者朋友批评指正。写书是一件严肃的事，书中的错误所有人都看得见，白纸黑字赖不掉的。我教过的很多学生都在大学里学过C语言，甚至考过二级，但程序写得一塌糊涂，连最基本的概念都搞错了，以前学过的C语言教材中的错误在他们脑子里根深蒂固，即使我纠正多次，他们仍然只记得以前学过的错误概念。这种有基础的学生还不如没有任何基础的学生教起来容易。我非常害怕我教给别人的知识也是错的，所以我仔细研究了C99之后才敢动笔写书。这本书涵盖的话题比较广泛，我竭尽全力也不足以保证书中的内容全部正确，还要依靠社区的力量一起来完善这本书，这样才能真正对读者负责，所以我选择将这本书开源。。
希望本书能成为你求学道路上的第一个伙伴。
宋劲杉 
2009年7月22日
目 录
上篇 C语言入门
第1章 程序的基本概念 2
1.1 程序和编程语言 2
1.2 自然语言和形式语言 6
1.3 程序的调试 7
1.4 第一个程序 9
第2章 常量、变量和表达式 12
2.1 继续Hello World 12
2.2 常量 15
2.3 变量 16
2.4 赋值 18
2.5 表达式 19
2.6 字符类型与字符编码 23
第3章 简单函数 24
3.1 数学函数 24
3.2 自定义函数 26
3.3 形参和实参 31
3.4 全局变量、局部变量和作用域 35
第4章 分支语句 41
4.1 if语句 41
4.2 if/else语句 43
4.3 布尔代数 45
4.4 switch语句 49
第5章 深入理解函数 51
5.1 return语句 51
5.2 增量式开发 54
5.3 递归 58
第6章 循环语句 64
6.1 while语句 64
6.2 do/while语句 66
6.3 for语句 67
6.4 break和continue语句 69
6.5 嵌套循环 70
6.6 goto语句和标号 71
第7章 结构体 74
7.1 复合类型与结构体 74
7.2 数据抽象 78
7.3 数据类型标志 82
7.4 嵌套结构体 84
第8章 数组 85
8.1 数组的基本概念 85
8.2 数组应用实例：统计随机数 88
8.3 数组应用实例：直方图 91
8.4 字符串 94
8.5 多维数组 95
第9章 编码风格 100
9.1 缩进和空白 100
9.2 注释 104
9.3 标识符命名 107
9.4 函数 108
9.5 indent工具 108
第10章 gdb 110
10.1 单步执行和跟踪函数调用 110
10.2 断点 117
10.3 观察点 121
10.4 段错误 125
第11章 排序与查找 128
11.1 算法的概念 128
11.2 插入排序 129
11.3 算法的时间复杂度分析 131
11.4 归并排序 133
11.5 线性查找 138
11.6 折半查找 139
第12章 栈与队列 144
12.1 数据结构的概念 144
12.2 堆栈 144
12.3 深度优先搜索 146
12.4 队列与广度优先搜索 152
12.5 环形队列 156
本阶段总结 159
下篇 C语言本质
第13章 计算机中数的表示 162
13.1 为什么计算机用二进制计数 162
13.2 不同进制之间的换算 164
13.3 整数的加减运算 165
13.3.1 Sign and Magnitude表示法 165
13.3.2 1's Complement表示法 166
13.3.3 2's Complement表示法 167
13.3.4 有符号数和无符号数 168
13.4 浮点数 169
第14章 数据类型详解 172
14.1 整型 172
14.2 浮点型 176
14.3 类型转换 177
14.3.1 Integer Promotion 177
14.3.2 Usual Arithmetic Conversion 178
14.3.3 由赋值产生的类型转换 179
14.3.4 强制类型转换 179
14.3.5 编译器如何处理类型转换 179
第15章 运算符详解 182
15.1 位运算 182
15.1.1 按位与、或、异或、取反运算 182
15.1.2 移位运算 183
15.1.3 掩码 184
15.1.4 异或运算的一些特性 185
15.2 其他运算符 186
15.2.1 复合赋值运算符 186
15.2.2 条件运算符 186
15.2.3 逗号运算符 187
15.2.4 sizeof运算符与typedef类型声明 187
15.3 Side Effect与Sequence Point 189
15.4 运算符总结 191
第16章 计算机体系结构基础 193
16.1 内存与地址 193
16.2 CPU 193
16.3 设备 196
16.4 MMU 198
16.5 Memory Hierarchy 201
第17章 x86汇编程序基础 205
17.1 最简单的汇编程序 205
17.2 x86的寄存器 208
17.3 第二个汇编程序 209
17.4 寻址方式 211
17.5 ELF文件 212
17.5.1 目标文件 213
17.5.2 可执行文件 218
第18章 汇编与C之间的关系 224
18.1 函数调用 224
18.2 main函数、启动例程和退出状态 230
18.3 变量的存储布局 237
18.4 结构体和联合体 244
18.5 C内联汇编 248
18.6 volatile限定符 250
第19章 链接详解 255
19.1 多目标文件的链接 255
19.2 定义和声明 260
19.2.1 extern和static关键字 260
19.2.2 头文件 264
19.2.3 定义和声明的详细规则 268
19.3 静态库 271
19.4 共享库 274
19.4.1 编译、链接、运行 274
19.4.2 函数的动态链接过程 281
19.4.3 共享库的命名惯例 282
19.5 虚拟内存管理 284
第20章 预处理 290
20.1 预处理的步骤 290
20.2 宏定义 291
20.2.1 函数式宏定义 291
20.2.2 内联函数 294
20.2.3 #、##运算符和可变参数 296
20.2.4 #undef预处理指示 298
20.2.5 宏展开的步骤 299
20.3 条件预处理指示 300
20.4 其他预处理特性 303
第21章 Makefile基础 306
21.1 基本规则 306
21.2 隐含规则和模式规则 313
21.3 变量 317
21.4 自动处理头文件的依赖关系 321
21.5 常用的make命令行选项 324
第22章 指针 327
22.1 指针的基本概念 327
22.2 指针类型的参数和返回值 331
22.3 指针与数组 332
22.4 指针与const限定符 335
22.5 指针与结构体 337
22.6 指向指针的指针与指针数组 337
22.7 指向数组的指针与多维数组 340
22.8 函数类型和函数指针类型 341
22.9 不完全类型和复杂声明 344
第23章 函数接口 349
23.1 本章的预备知识 349
23.1.1 strcpy与strncpy 349
23.1.2 malloc与free 354
23.2 传入参数与传出参数 358
23.3 两层指针的参数 360
23.4 返回值是指针的情况 362
23.5 回调函数 365
23.6 可变参数 368
第24章 C标准库 372
24.1 字符串操作函数 373
24.1.1 给字符串赋初值 373
24.1.2 取字符串的长度 374
24.1.3 拷贝字符串 375
24.1.4 连接字符串 377
24.1.5 比较字符串 378
24.1.6 搜索字符串 379
24.1.7 分割字符串 380
24.2 标准I/O库函数 383
24.2.1 文件的基本概念 383
24.2.2 fopen/fclose 384
24.2.3 stdin/stdout/stderr 387
24.2.4 errno与perror/strerror函数 388
24.2.5 以字节为单位的I/O函数 391
24.2.6 操作读写位置的函数 393
24.2.7 以字符串为单位的I/O函数 395
24.2.8 以记录为单位的I/O函数 397
24.2.9 格式化I/O函数 399
24.2.10 C标准库的I/O缓冲区 406
24.2.11 本节综合练习 410
24.3 数值字符串转换函数 412
24.4 分配内存的函数 414
第25章 链表、二叉树和哈希表 415
25.1 链表 415
25.1.1 单链表 415
25.1.2 双向链表 421
25.1.3 静态链表 425
25.1.4 本节综合练习 426
25.2 二叉树 426
25.2.1 二叉树的基本概念 426
25.2.2 排序二叉树 432
25.3 哈希表 437
本阶段总结 439
附录A 字符编码 442
索引 449
参考书目 474