《零基础学C语言(第4版)》分为“C语言基础”“一窥C语言门径”“C语言进阶”“C语言程序设计实例与面试题解析”四篇,系统全面地介绍了C语言各个方面的知识,从最简单的“Hello World”程序写起,逐步深化、细化,第一篇。书中对每个知识和技术要点都给出了翔实的示例及代码分析。和其他书籍中罗列代码的做法不同,本书中的代码力求短小精悍,直击要点,避免了细枝末节对读者思维的干扰。在讲解知识点的同时辅以笔者多年的C语言编程经验解析,可加深读者的理解。
封面图
目录
- 前言
- 第一篇 C语言基础
- 第1章 踏上征程前的思想动员1
- 1.1 为什么选择C语言1
- 1.2 如何学好C语言3
- 1.3 语言概述3
- 1.3.1 什么是语言3
- 1.3.2 什么是机器语言3
- 1.3.3 什么是汇编语言4
- 1.3.4 面向过程的语言5
- 1.3.5 什么是C语言5
- 1.4 程序的开发周期5
- 1.4.1 编辑C源代码6
- 1.4.2 编译C源代码6
- 1.4.3 连接目标文件7
- 1.4.4 编译连接过程示例7
- 1.4.5 运行程序9
- 1.5 C、C++、VC++的区别和开发环境9
- 1.6 小结11
- 1.7 习题11
- 第2章 跟我写Hello World13
- 2.1 了解需求才能创建程序13
- 2.2 认识Code::Blocks开发环境13
- 2.2.1 为什么选择Code::Blocks14
- 2.2.2 启动Code::Blocks14
- 2.2.3 新建Hello World项目14
- 2.2.4 定义新项目15
- 2.2.5 添加源代码到项目16
- 2.2.6 调试器设置16
- 2.2.7 开始编辑代码17
- 2.3 编译运行18
- 2.4 调试排错(debug)19
- 2.4.1 debug的由来19
- 2.4.2 设置断点20
- 2.4.3 调试运行20
- 2.5 第一个程序容易出现的错误21
- 2.5.1 包含命令include21
- 2.5.2 关键字main22
- 2.5.3 表示代码行结束的分号22
- 2.6 小结22
- 2.7 习题22
- 第3章 分解Hello World——最简单C程序的组成24
- 3.1 C程序的构成24
- 3.2 C程序的注释25
- 3.3 C程序必须有的main函数26
- 3.4 调用函数在屏幕上显示文字27
- 3.5 #include预处理器指示符28
- 3.5.1 函数声明及其作用28
- 3.5.2 试验寻找#include的作用29
- 3.5.3 #include的作用30
- 3.6 计算1+1的程序实例31
- 3.7 数据从哪里来,又到哪里去——变量32
- 3.7.1 变量在内存中的表现形式32
- 3.7.2 编译器使用变量符号表32
- 3.7.3 变量及其使用33
- 3.8 自己设计C函数35
- 3.8.1 在main函数中计算3个整数的平均数35
- 3.8.2 在main函数中分3次计算3个整数的平均数36
- 3.8.3 自编函数实现计算3个整数的平均数36
- 3.8.4 如何自编写函数37
- 3.8.5 观察总结函数声明和函数定义的意义38
- 3.9 语句构成程序39
- 3.10 优秀程序员的代码风格40
- 3.11 小结40
- 3.12 习题41
- 第4章 常量、变量及数据类型42
- 4.1 计算机是如何表示数据的42
- 4.1.1 二进制、八进制、十六进制42
- 4.1.2 表示数据的字节和位44
- 4.1.3 内存是存储数据的房间45
- 4.2 数据类型46
- 4.2.1 整数类型46
- 4.2.2 整数的有符号和无符号48
- 4.2.3 实数类型50
- 4.2.4 字符类型50
- 4.2.5 数据类型总结51
- 4.3 常量51
- 4.3.1 直接常量和符号常量52
- 4.3.2 符号常量的优点53
- 4.3.3 直接常量的书写格式54
- 4.3.4 转义字符55
- 4.3.5 字符串57
- 4.4 变量58
- 4.4.1 变量的声明58
- 4.4.2 变量声明的意义59
- 4.4.3 标识符和关键字60
- 4.4.4 变量在内存中占据的空间和变量的值62
- 4.4.5 为变量赋初值64
- 4.4.6 变量使用时常见的错误65
- 4.5 几个与变量相关的经典算法66
- 4.5.1 累加和累乘66
- 4.5.2 交换两个变量的值68
- 4.6 小结69
- 4.7 习题69
- 第5章 用屏幕和键盘交互——简单的输出和输入71
- 5.1 输入—处理—输出:这就是程序71
- 5.2 向屏幕输出——printf()函数详解72
- 5.2.1 printf()函数的一般形式72
- 5.2.2 printf()函数的输出原理73
- 5.2.3 格式控制字符串的一般形式74
- 5.2.4 输出带符号的整数%d75
- 5.2.5 设置最小宽度的输出75
- 5.2.6 长整型输出%ld76
- 5.2.7 输出八进制形式76
- 5.2.8 输出十六进制的形式77
- 5.2.9 输出十进制的unsigned型数据77
- 5.2.10 输出字符78
- 5.2.11 输出字符串%s79
- 5.2.12 输出实型数据%f81
- 5.2.13 输出指数形式的实数82
- 5.2.14 自动选择%f或者%e形式输出%g83
- 5.2.15 printf()函数的几点说明83
- 5.3 字符输出putchar()和字符串输出puts()84
- 5.3.1 字符输出函数84
- 5.3.2 字符串输出函数85
- 5.4 接收键盘输入——scanf()函数详解86
- 5.4.1 scanf()函数的一般形式86
- 5.4.2 scanf()函数的输入原理87
- 5.4.3 多数据输入分隔规则89
- 5.4.4 控制输入的格式字符90
- 5.4.5 scanf()函数的使用说明91
- 5.4.6 使用scanf()函数的注意事项93
- 5.5 字符输入函数getchar()95
- 5.6 输入和输出程序举例96
- 5.7 小结98
- 5.8 习题99
- 第6章 程序的基本构成——运算符和表达式100
- 6.1 认识C中的运算符和表达式100
- 6.1.1 运算符和表达式100
- 6.1.2 操作数、运算符和表达式101
- 6.1.3 C运算符简介102
- 6.2 算术运算符和算术表达式102
- 6.2.1 基本的算术运算符103
- 6.2.2 ++自增、--自减运算符104
- 6.2.3 算术表达式和运算符的优先级及结合性106
- 6.3 逗号运算符和逗号表达式107
- 6.3.1 逗号表达式的一般形式107
- 6.3.2 逗号表达式的优先级和结合性108
- 6.4 关系运算符和关系表达式109
- 6.4.1 关系运算符的种类109
- 6.4.2 关系表达式的一般形式109
- 6.5 逻辑运算符和逻辑表达式110
- 6.5.1 逻辑运算符111
- 6.5.2 逻辑真值表111
- 6.6 赋值运算符和赋值表达式112
- 6.6.1 赋值表达式112
- 6.6.2 复合运算符113
- 6.7 强制类型转换和自动类型转换113
- 6.7.1 强制类型转换113
- 6.7.2 自动类型转换115
- 6.8 运算符的优先级116
- 6.8.1 优先级、结合性汇总116
- 6.8.2 sizeof运算117
- 6.9 取地址运算符117
- 6.10 小结118
- 6.11 习题118
- 第7章 程序的最小独立单元——语句120
- 7.1 5种语句类型120
- 7.1.1 表达式语句120
- 7.1.2 函数调用语句122
- 7.1.3 空语句122
- 7.1.4 复合语句(块语句)122
- 7.1.5 流程控制语句123
- 7.2 结构化程序设计123
- 7.2.1 什么是算法123
- 7.2.2 算法的表示123
- 7.2.3 算法的伪代码表示124
- 7.2.4 算法的流程图表示124
- 7.2.5 3种控制结构124
- 7.2.6 算法示例125
- 7.3 小结125
- 7.4 习题126
- 第8章 条件判断——分支结构127
- 8.1 if语句127
- 8.1.1 判断表达式127
- 8.1.2 花括号和if结构体128
- 8.2 if...else结构129
- 8.2.1 关键在else129
- 8.2.2 if...else结构体130
- 8.3 多分支语句和分支语句嵌套131
- 8.3.1 多分支131
- 8.3.2 多分支if结构133
- 8.3.3 分支语句嵌套134
- 8.4 switch结构135
- 8.4.1 一般形式135
- 8.4.2 为什么叫开关语句137
- 8.4.3 default语句138
- 8.4.4 if结构和switch结构之比较139
- 8.4.5 switch结构的常见错误与解决方法139
- 8.5 小结140
- 8.6 习题141
- 第9章 一遍又一遍——循环结构142
- 9.1 构造循环142
- 9.1.1 循环的条件142
- 9.1.2 当型循环和直到型循环143
- 9.2 while和do...while循环结构143
- 9.2.1 语法规则144
- 9.2.2 代码块145
- 9.2.3 while语句的常见错误145
- 9.2.4 do...while语句的常见错误146
- 9.3 for循环结构147
- 9.3.1 基本形式147
- 9.3.2 表达式省略149
- 9.3.3 循环终止和步长150
- 9.3.4 for语句的常见错误150
- 9.4 循环嵌套151
- 9.4.1 嵌套示例151
- 9.4.2 嵌套的效率152
- 9.4.3 循环嵌套程序的常见错误153
- 9.5 与循环密切相关的流程转向控制语句154
- 9.5.1 用break跳出循环154
- 9.5.2 用continue重来一次155
- 9.5.3 用goto实现跳转156
- 9.6 小结157
- 9.7 习题157
- 第二篇 一窥C语言门径
- 第10章 同一类型多个元素的集合——简单数组159
- 10.1 什么是数组159
- 10.1.1 数组是一大片连续内存空间159
- 10.1.2 数组元素的访问160
- 10.2 一维数组160
- 10.2.1 一维数组的声明160
- 10.2.2 一维数组元素的访问161
- 10.2.3 一维数组的初始化162
- 10.2.4 不合法的数组操作163
- 10.3 二维数组164
- 10.3.1 二维数组的声明164
- 10.3.2 二维数组的初始化164
- 10.3.3 二维数组应用举例165
- 10.4 更高维的数组166
- 10.4.1 高维数组的声明和元素访问166
- 10.4.2 初始化166
- 10.4.3 多维数组在内存中是如何排列元素的167
- 10.5 小结168
- 10.6 习题168
- 第11章 写程序就是写函数——函数入门170
- 11.1 什么是函数170
- 11.1.1 函数的由来170
- 11.1.2 C语言中的函数170
- 11.2 自定义函数171
- 11.2.1 函数定义语法171
- 11.2.2 函数定义范例172
- 11.2.3 不要重复定义173
- 11.3 函数调用与返回173
- 11.3.1 形参和实参174
- 11.3.2 传址调用175
- 11.3.3 函数返回176
- 11.4 告诉编译器有这么一个函数177
- 11.4.1 函数声明的语法177
- 11.4.2 声明不同于定义179
- 11.4.3 标准库函数的声明180
- 11.5 函数的调用过程180
- 11.6 小结180
- 11.7 习题180
- 第12章 C语言难点——指针初探182
- 12.1 计算机中的内存182
- 12.1.1 内存地址182
- 12.1.2 内存中保存的内容183
- 12.1.3 地址就是指针183
- 12.2 指针的定义183
- 12.2.1 指针变量的声明183
- 12.2.2 指针变量的初始化184
- 12.2.3 指针变量的值185
- 12.2.4 取地址操作符&185
- 12.2.5 指针变量占据一定的内存空间185
- 12.2.6 指向指针的指针186
- 12.2.7 指针变量常见的错误分析与解决186
- 12.3 使用指针187
- 12.3.1 运算符*188
- 12.3.2 指针的类型和指针所指向的类型189
- 12.3.3 同类型指针的赋值189
- 12.3.4 void指针190
- 12.3.5 指针的类型和指针所指向的类型不同190
- 12.4 指针的运算192
- 12.4.1 算术运算之“指针+整数”或“指针-整数”192
- 12.4.2 指针-指针193
- 12.4.3 指针的大小比较194
- 12.5 指针表达式与左值194
- 12.5.1 指针与整型194
- 12.5.2 指针与左值195
- 12.5.3 指针与const195
- 12.6 动态内存分配196
- 12.6.1 动态分配的好处196
- 12.6.2 malloc与free函数197
- 12.6.3 calloc与free198
- 12.6.4 free函数与指针199
- 12.6.5 内存泄漏199
- 12.6.6 释放已经释放了的内存会出问题200
- 12.7 小结200
- 12.8 习题200
- 第13章 字符串及字符串操作202
- 13.1 C风格字符串202
- 13.1.1 C风格字符串的声明202
- 13.1.2 C风格字符串在内存中的表示202
- 13.2 字符数组的输入输出203
- 13.2.1 字符数组的声明203
- 13.2.2 字符数组可以进行整体输入输出204
- 13.2.3 使用gets()函数读取整行205
- 13.2.4 访问字符数组中某个元素205
- 13.2.5 使用puts()函数实现字符串的输出206
- 13.2.6 使用字符数组的常见问题206
- 13.3 字符串处理函数207
- 13.3.1 理解:数组名是常指针208
- 13.3.2 strlen()函数与size_t210
- 13.3.3 字符串复制函数strcpy()211
- 13.3.4 字符串比较函数strcmp()212
- 13.3.5 字符串连接函数strcat()213
- 13.3.6 全转换为大写形式213
- 13.3.7 链式操作214
- 13.4 小结214
- 13.5 习题215
- 第14章 结构体、共用体、枚举和typedef216
- 14.1 结构体216
- 14.1.1 结构体的定义216
- 14.1.2 声明结构体变量217
- 14.1.3 初始化结构变量218
- 14.1.4 访问结构体成员218
- 14.1.5 结构体定义的位置219
- 14.1.6 结构体变量赋值219
- 14.2 特殊结构体220
- 14.2.1 结构体嵌套220
- 14.2.2 匿名结构体223
- 14.3 共用体224
- 14.3.1 什么是共用体224
- 14.3.2 共用体的定义224
- 14.3.3 声明共用体变量225
- 14.3.4 共用体变量的初始化225
- 14.3.5 共用体成员访问225
- 14.3.6 共用体赋值226
- 14.4 结构体和共用体的内存差异226
- 14.4.1 结构体变量和共用体变量内存形式的不同227
- 14.4.2 结构体变量的内存大小227
- 14.4.3 字节对齐228
- 14.4.4 最宽基本类型228
- 14.4.5 共用体的大小229
- 14.5 枚举类型230
- 14.5.1 什么是枚举类型230
- 14.5.2 枚举类型的定义230
- 14.5.3 声明枚举变量231
- 14.5.4 枚举常量是什么231
- 14.5.5 使用枚举时常见的错误232
- 14.6 给类型取个别名——typedef233
- 14.6.1 typedef基本用法233
- 14.6.2 #define用法233
- 14.7 小结234
- 14.8 习题234
- 第15章 如何节省内存——位运算235
- 15.1 什么是位运算235
- 15.1.1 开灯关灯235
- 15.1.2 改变状态235
- 15.1.3 计算机中的数据存储形式236
- 15.2 位逻辑运算符237
- 15.2.1 位取反操作237
- 15.2.2 位与运算237
- 15.2.3 位或运算237
- 15.2.4 位异或238
- 15.2.5 实例分析238
- 15.3 移位运算239
- 15.3.1 基本形式239
- 15.3.2 移位举例239
- 15.3.3 移位和乘以2241
- 15.4 小结241
- 15.5 习题241
- 第三篇 C语言进阶主题
- 第16章 存储不仅仅局限于内存——文件243
- 16.1 什么是文件243
- 16.1.1 文件243
- 16.1.2 流244
- 16.1.3 重定向244
- 16.1.4 文件的处理形式——缓冲区和非缓冲区245
- 16.1.5 文件的存储形式——文本形式和二进制形式245
- 16.2 C语言如何使用文件245
- 16.2.1 文件型指针245
- 16.2.2 文件操作的步骤246
- 16.3 文件的打开与关闭246
- 16.3.1 用于打开文件的fopen()函数247
- 16.3.2 打开是否成功248
- 16.3.3 用于关闭文件的fclose()函数249
- 16.4 文件的读写249
- 16.4.1 读写的相对参照249
- 16.4.2 如何判断文件已经结束249
- 16.4.3 字符读写函数fgetc()和fputc()250
- 16.4.4 字符串读写函数fgets()和fputs()251
- 16.4.5 块读写函数fread()和fwrite()253
- 16.4.6 格式化文件输入输出fprintf()与fscanf()256
- 16.5 文件的定位258
- 16.5.1 移动指针到文件开头rewind()258
- 16.5.2 移动指针到当前位置ftell()258
- 16.5.3 移动指针fseek()258
- 16.6 小结260
- 16.7 习题260
- 第17章 灵活却难以理解——指针进阶262
- 17.1 指针与数组262
- 17.1.1 数组名指针262
- 17.1.2 使用数组名常指针表示数组元素263
- 17.1.3 指向数组元素的指针变量263
- 17.1.4 指向数组的指针变量264
- 17.1.5 指针数组265
- 17.1.6 指针与数组的常见问题266
- 17.2 指针、结构体和结构体数组266
- 17.2.1 两种访问形式266
- 17.2.2 声明创建一个结构体数组267
- 17.2.3 结构体数组的初始化267
- 17.2.4 结构体数组的使用268
- 17.2.5 指向结构体数组的指针268
- 17.3 函数指针269
- 17.3.1 函数名指针269
- 17.3.2 指向函数的指针270
- 17.3.3 函数指针类型272
- 17.3.4 函数指针作函数参数273
- 17.3.5 函数指针数组274
- 17.3.6 指向函数指针的指针275
- 17.4 小结275
- 17.5 习题276
- 第18章 更深入的理解——函数进阶277
- 18.1 参数传递的副本机制277
- 18.1.1 传值调用的副本277
- 18.1.2 传址调用的副本机制278
- 18.2 函数返回值的副本机制281
- 18.2.1 return 局部变量为什么合法281
- 18.2.2 返回指针申请动态内存282
- 18.2.3 不要返回指向栈内存的指针282
- 18.2.4 返回指向只读存储区的指针283
- 18.3 函数与结构体283
- 18.3.1 结构体变量的传值和传址调用283
- 18.3.2 结构体变量的成员作为函数参数284
- 18.3.3 返回结构体的函数285
- 18.3.4 返回结构体指针的函数286
- 18.4 函数与数组286
- 18.4.1 数组元素作为函数参数286
- 18.4.2 数组名作为函数参数287
- 18.4.3 多维数组名作为函数参数289
- 18.4.4 数组名作函数参数时的退化290
- 18.5 递归290
- 18.5.1 递归流程290
- 18.5.2 递归两要素292
- 18.5.3 效率VS可读性293
- 18.6 带参数的主函数294
- 18.7 小结295
- 18.8 习题295
- 第19章 生存期、作用域与可见域297
- 19.1 内存分配297
- 19.1.1 内存分区297
- 19.1.2 变量的存储类别298
- 19.1.3 生存期299
- 19.1.4 作用域与可见域299
- 19.2 auto变量299
- 19.2.1 定义格式300
- 19.2.2 作用域和生存期300
- 19.2.3 auto变量的屏蔽准则301
- 19.2.4 重复定义302
- 19.2.5 auto变量的初始化和特点302
- 19.3 register变量303
- 19.3.1 定义格式303
- 19.3.2 使用举例303
- 19.4 extern变量304
- 19.4.1 全局变量定义304
- 19.4.2 全局变量声明305
- 19.4.3 可见域306
- 19.4.4 全局变量的屏蔽准则307
- 19.4.5 全局变量的利与弊309
- 19.5 static变量309
- 19.5.1 定义格式309
- 19.5.2 静态局部变量310
- 19.5.3 静态全局变量311
- 19.5.4 静态局部变量和静态全局变量的区别312
- 19.5.5 extern变量和static变量的初始化312
- 19.6 函数的作用域与可见域312
- 19.6.1 内部函数313
- 19.6.2 外部函数314
- 19.7 结构体定义的作用域与可见域314
- 19.7.1 定义位置与可见域314
- 19.7.2 允许重复定义315
- 19.8 常见的有关变量存储的错误316
- 19.9 小结318
- 19.10 习题318
- 第20章 编译及预处理320
- 20.1 编译流程320
- 20.1.1 编辑321
- 20.1.2 预处理321
- 20.1.3 编译321
- 20.1.4 连接322
- 20.2 程序错误322
- 20.2.1 错误分类323
- 20.2.2 编译错误323
- 20.2.3 连接错误323
- 20.2.4 逻辑错误323
- 20.2.5 排错324
- 20.3 预处理命令之宏定义324
- 20.3.1 宏定义324
- 20.3.2 不带参数的宏定义324
- 20.3.3 带参数的宏定义326
- 20.3.4 #define定义常量与const常量328
- 20.3.5 文件包含329
- 20.3.6 条件编译330
- 20.3.7 宏函数331
- 20.4 小结332
- 20.5 习题333
- 第21章 数据结构334
- 21.1 链表334
- 21.1.1 链表的结构334
- 21.1.2 创建链表并遍历输出335
- 21.1.3 链表的插入338
- 21.1.4 链表结点的删除341
- 21.1.5 链表的逆置342
- 21.1.6 链表的销毁344
- 21.1.7 链表的综合实例344
- 21.1.8 循环链表349
- 21.1.9 双链表349
- 21.2 栈和队列352
- 21.2.1 栈的定义353
- 21.2.2 栈的分类353
- 21.2.3 栈的操作353
- 21.2.4 函数与栈356
- 21.2.5 队列356
- 21.3 自定义类型359
- 21.4 小结361
- 21.5 习题362
- 第四篇 C语言程序设计实例与面试题解析
- 第22章 面试题解析363
- 22.1 基础知识363
- 22.1.1 指针自增自减有什么不同363
- 22.1.2 什么是递归364
- 22.1.3 宏定义与操作符的区别364
- 22.1.4 引用与值传递的区别364
- 22.1.5 指针和引用有什么区别364
- 22.1.6 什么是栈364
- 22.1.7 main函数执行前还会执行什么代码364
- 22.1.8 static有什么用途365
- 22.1.9 定义int **a[3][4], 则变量占用的内存空间为多少365
- 22.1.10 什么是预编译365
- 22.1.11 int (*s[10])(int)表示什么意义365
- 22.1.12 结构体与共同体有何区别365
- 22.2 算法和思维逻辑知识366
- 22.2.1 100美元哪里去了366
- 22.2.2 将16升水平均分给四个人366
- 22.2.3 算出小王买了几瓶啤酒、几瓶饮料367
- 22.2.4 找出不同的苹果367
- 22.2.5 找出不同的球368
- 22.2.6 猜自己的帽子颜色368
- 22.2.7 3筐水果各是什么370
- 22.2.8 最后剩下的是谁370
- 22.2.9 聪明的商人371
- 22.2.10 红球和白球371
- 22.2.11 乌龟赛跑372
- 22.2.12 投硬币372
- 附录 ASCII编码表373