基本信息·出版社:电子工业出版社 ·页码:463 页 ·出版日期:2009年12月 ·ISBN:9787121097713 ·条形码:9787121097713 ·版本:第1版 ·装帧:平装 ...
商家名称 |
信用等级 |
购买信息 |
订购本书 |
|
 |
Linux C编程一站式学习 |
 |
|
 |
Linux C编程一站式学习 |
 |

基本信息·出版社:电子工业出版社
·页码:463 页
·出版日期:2009年12月
·ISBN:9787121097713
·条形码:9787121097713
·版本:第1版
·装帧:平装
·开本:16
·正文语种:中文
·丛书名:嵌入式技术丛书,亚嵌教育作品系列
内容简介 《Linux C编程一站式学习》有两条线索,一条线索是以Linux平台为载体全面深入地介绍c语言的语法和程序的工作原理,另一条线索是介绍程序设计的基本思想和开发调试方法。《Linux C编程一站式学习》分为两部分:第一部分讲解编程语言和程序设计的基本思想方法,让读者从概念上认识c语言;第二部分结合操作系统和体系结构的知识讲解程序的工作原理,让读者从本质上认识C语言。
《Linux C编程一站式学习》适合做零基础的初学者学习c语言的第一本教材,帮助读者打下牢固的基础。有一定的编程经验但知识体系不够完整的读者也可以对照《Linux C编程一站式学习》查缺补漏,从而更深入地理解程序的工作原理。《Linux C编程一站式学习》最初是为北京亚嵌教育研究中心的嵌入式Linux系统工程师就业班课程量身定做的教材之一,也适合作为高等院校程序设计基础课程的教材。《Linux C编程一站式学习》对于C语言的语法介绍得非常全面,对C99标准做了很多解读,因此也可以作为一本精简的c语言语法参考书。
作者简介 宋劲杉,亚嵌教育资深讲师,清华大学自动化系硕士,6年嵌入式系统开发经验,3年嵌入式行业教学经验,精通Linux内核、POSIX、TCP/IP,擅长ARM平台的Linux系统移植和应用开发,目前关注的方向有分布式系统、动态语言。爱好:开源软件、电子音乐、HomeParty。
编辑推荐 《Linux C编程一站式学习》:嵌入式技术丛书,亚嵌教育作品系列
目录 上篇 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
……
序言 本书最初是为北京亚嵌教育研究中心的嵌入式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,学习完本书之后读者有了一个全局观,再去学习那些参考资料就应该很容易上手了。
文摘 插图:

在这种情况下递归程序比循环程序更容易理解。此外还有一点不同:如图5.2所示,在整个递归调用过程中,虽然分配和释放了很多变量,但所有变量都只在初始化时赋值,没有任何变量的值发生过改变,而上面的循环程序则通过对n和resul-t这两个变量多次赋值来达到同样的目的。前一种思路称为函数式编程(Functional Programming),而后一种思路称为命令式编程(Imperative Programming),这个区别类似于第1.1节中讲的Declarative和Imperative的区别。函数式编程的“函数”类似于数学函数的概念,回顾一下第3.1节所讲的,数学函数是没有Side Effect的,而C语言的函数可以有Side Effect,比如在一个函数中修改某个全局变量的值就是一种SideEffect。第3.4节指出,全局变量被多次赋值会给调试带来麻烦,如果一个函数体很长,控制流程很复杂,那么局部变量被多次赋值也会有同样的问题。因此,不要以为“变量可以多次赋值”是天经地义的,有很多编程语言可以完全采用函数式编程的模式,避免Side Effect,例如LISP、Haskell、Erlang等。用c语言编程主要还是采用Imperative的模式,但要记住,给变量多次赋值时要格外小心,在代码中多次读写同一变量应该以一种一致的方式进行。所谓“一致的方式”是说应该有一套统一的规则,规定在一段代码中哪里会对某个全局变量赋值、哪里会读取它的值,比如在第24.2.4节我们会讲到访问errno的规则。