第1章 C语言的“三观”和提问的智慧 1
1.1C语言的“三观” 1
1.1.1内存观 1
1.1.2代码观 2
1.1.3调试观 2
1.2提问的智慧 3
1.2.1提问之前应该做的事情 3
1.2.2提问模板 4
1.2.3提问时的建议 5
1.2.4提问者要谨记 6
1.3小结 6
第2章 开发环境安装与配置 7
2.1安装MinGW 7
2.1.1在线安装MinGW-w64 7
2.1.2离线安装MinGW-w64 10
2.1.3测试MinGW-w64 11
2.1.4配置Windows的Path环境变量 12
2.1.5命令行开发C语言程序 14
2.1.6 “Makefile”编译/链接C语言程序 18
2.2开发IDE——Code∷Blocks 21
2.2.1下载Code∷Blocks 21
2.2.2安装Code∷Blocks 22
2.2.3配置Code∷Blocks 24
2.2.4测试Code∷Blocks 26
2.3小结 27
第3章 Code∷Blocks的工程及其应用 28
3.1Code∷Blocks中的工程 28
3.1.1创建工程 28
3.1.2 “cbp”工程文件 31
3.1.3工程设置的变更 31
3.1.4构建工程 33
3.1.5其它相关文件 34
3.2在工程中添加/删除文件 35
3.2.1为工程新建文件 35
3.2.2为工程添加文件 36
3.2.3为工程删除文件 38
3.3工作区 39
3.4小结 40
第4章 DEBUG的概念及其使用 41
4.1DEBUG的概念 41
4.2在Code∷Blocks中进行DEBUG 42
4.2.1配置Debugger 42
4.2.2 DEBUG菜单与工具栏 43
4.2.3添加程序运行断点 44
4.2.4 DEBUG窗口 46
4.2.5查看程序运行状态 48
4.2.6单步执行程序 48
4.2.7修改并继续调试程序 49
4.2.8结束程序调试 51
4.2.9调试操作失效的处理 51
4.3在命令行DEBUG程序 52
4.3.1在命令行编译链接程序 52
4.3.2在命令行启动gdb调试器调试程序 53
4.4小结 57
第5章 scanf()函数及键盘缓冲区 58
5.1输入流和输入缓冲区的概念 58
5.2数据输入实例分析 59
5.2.1读入整型数据存入字符型变量 59
5.2.2读入字符型数据存入整型变量 62
5.2.3读入字符型数据存入字符型变量 63
5.2.4格式串中的空格 64
5.2.5scanf()其它输入函数混合使用 67
5.3删除scanf()函数留下的?n? 68
5.3.1使用循环删除 68
5.3.2使用正则表达式删除 68
5.4小结 69
第6章 数据类型的本质 70
6.1数据存储方式 70
6.1.1整型数据 70
6.1.2浮点型数据 70
6.2基本数据类型 71
6.2.1字符型char 71
6.2.2整型int 73
6.2.3浮点型float 74
6.2.4空类型void 74
6.3类型修饰符 75
6.3.1修饰内存大小 75
6.3.2修饰符号位 76
6.3.3内存访问限制 77
6.4 sizeof()运算符 77
6.5衍生数据类型 78
6.6类型转换 81
6.6.1类型级别 82
6.6.2隐式类型转换 82
6.6.3强制类型转换 83
6.7小结 83
第7章 类型错误引起的内存紊乱 84
7.1内存非法访问 84
7.1.1scanf()函数格式串不匹配问题 84
7.1.2内存状态分析 85
7.2内存合法访问 86
7.2.1调整变量声明顺序 87
7.2.2合法内存的不合理使用 87
7.3意外改写指针值 89
7.3.1使用指针读入数据 89
7.3.2指针值的变化 90
7.4小结 92
第8章 浮点数及其使用 93
8.1浮点数 93
8.2 IEEE754标准浮点数 93
8.2.1规格化数 94
8.2.2非规格化数 94
8.2.3特殊数 94
8.3 IEEE754标准浮点存储格式 94
8.3.1单精度格式 95
8.3.2双精度格式 95
8.3.3双精度扩展格式(SPARC结构) 96
8.3.4双精度扩展格式(x86) 96
8.4使用浮点数时的注意事项 97
8.4.1交换定律不适用浮点数 97
8.4.2计算顺序影响结果 97
8.4.3避免对两个实数做是否相等的判断 98
8.4.4慎用浮点数作为循环变量 99
8.4.5避免数量级相差很大的数直接加减 100
8.4.6浮点数的乘除运算 100
8.4.7尽量使用double型以提高精度 100
8.4.8浮点数的特殊数 101
8.5小结 102
第9章 “自顶向下,逐步求精”的程序设计方法 103
9.1结构化程序设计 103
9.2计数控制循环 103
9.3哨兵控制循环 105
9.4结构嵌套 108
9.5算法的伪代码描述 111
9.6小结 112
第10章 函数及其注意事项 113
10.1函数概述 113
10.1.1函数声明 113
10.1.2函数定义 114
10.1.3函数调用 117
10.1.4函数的使用步骤和方法 117
10.2常见问题 117
10.2.1嵌套定义 118
10.2.2 “return”语句不完整 118
10.2.3参数重复声明 119
10.2.4函数头后有“;” 119
10.2.5形参声明格式错误 119
10.2.6返回值与返回类型不一致 120
10.2.7期望函数返回多个值 120
10.2.8期望函数参数双向传递 120
10.2.9实参与形参不一致 121
10.2.10函数定义代替函数声明 121
10.3小结 122
第11章 函数参数的单向值传递 123
11.1值传递概述 123
11.2交换两个变量的值 123
11.2.1直接交换 123
11.2.2使用普通形参变量通过函数实现交换 124
11.2.3使用指针形参变量通过函数实现交换 125
11.2.4使用指针形参变量通过交换地址实现交换 126
11.3 DEBUG及代码剖析 127
11.3.1普通变量作为形参 127
11.3.2指针变量作为形参 129
11.3.3指针变量作为形参但交换地址 132
11.4小结 133
第12章 递归函数 134
12.1递归的概念 134
12.2递归范式 134
12.3数学函数 135
12.3.1阶乘函数 135
12.3.2求幂函数 136
12.3.3求最大公约数函数 137
12.3.4求斐波那契数列 138
12.4递归跳跃的信任 138
12.5其它递归示例 139
12.5.1探测回文 139
12.5.2折半查找 140
12.6避免递归中常见的错误 141
12.7小结 142
第13章 一维数组的本质 143
13.1一维数组的概念 143
13.2数组的声明 143
13.3数组名的内涵 145
13.4“[]”运算符和数组下标引用 146
13.5“&a”“a”和“&a[0]” 147
13.6数组惯用法 148
13.6.1确定数组元素的长度 148
13.6.2直接操作数组内存 149
13.6.3数组作为函数的形参 149
13.6.4字符串常量——另类数组 152
13.7小结 153
第14章 多维数组的本质 154
14.1多维数组的声明 154
14.2多维数组数组名的层级关系 155
14.3多维数组数组名的内涵 156
14.4数组类型 157
14.5“a”“&a”“a[0]”“&a[0]”和“&a[0][0]” 158
14.6指向数组的指针 159
14.7多维数组惯用法 161
14.7.1二维数组的一维数组操作模式 161
14.7.2直接操作数组内存 163
14.7.3作为函数的形参 163
14.8小结 166
第15章 二级指针和二维数组 167
15.1概述 167
15.2二级指针指向二维数组 167
15.3通过二级指针操作二维数组 170
15.4小结 172
第16章 指针 173
16.1指针声明 173
16.2指针的内涵 174
16.2.1指针的类型 174
16.2.2指针所指向的对象的类型 175
16.2.3指针的值 176
16.2.4指针本身所占据的内存区 176
16.3指针的运算 176
16.3.1指针加上或减去一个整数 176
16.3.2两个指针相减 179
16.3.3指针的比较 179
16.4&和*运算符 180
16.5指针和const 180
16.6函数指针 181
16.7小结 188
第17章 结构体类型 189
17.1结构体类型概述 189
17.1.1结构体类型的定义 189
17.1.2声明结构体类型的变量 190
17.1.3结构体成员的基本操作 191
17.1.4结构体类型变量的整体赋值 191
17.1.5结构体类型的综合应用实例 194
17.1.6结构体常量(C99) 196
17.1.7结构体类型的其它使用方式 197
17.1.8使用“typedef”为结构体类型定义别名 197
17.2包含自身结构体地址类型的指针成员 198
17.3小结 202
第18章 结构体变量的浅拷贝和深拷贝 203
18.1指针成员 203
18.2动态内存分配 204
18.3结构体变量的销毁 205
18.4浅拷贝 205
18.4.1直接赋值 205
18.4.2悬空指针 207
18.5深拷贝 208
18.5.1重新分配内存空间 208
18.5.2内存的独立销毁 209
18.5.3深拷贝的调用时机 210
18.6小结 210
第19章 在结构体中使用函数指针 211
19.1函数指针的概念 211
19.2在结构体中使用函数指针 212
19.3小结 220
第20章 动态内存分配与管理 221
20.1野指针 221
20.2 void*——万能指针 221
20.3数据段、代码段、栈和堆 222
20.4内存分配与管理函数 223
20.5动态数组 224
20.5.1动态一维数组 224
20.5.2动态二维数组 226
20.5.3柔性数组(C99) 230
20.6内存使用的常见错误及对策 231
20.6.1结构体指针成员未初始化 231
20.6.2未能分配足够内存 233
20.6.3分配的内存太小 233
20.6.4内存分配成功但未初始化 234
20.6.5对函数的入口进行校验 234
20.7小结 236
第21章 用“void*”指针实现泛型和多态编程 237
21.1多态性的概念 237
21.2结构体和单向链表 237
21.3函数指针 238
21.4泛型链表 240
21.5异质链表 242
21.6小结 248
第22章 泛型排序程序设计 249
22.1泛型程序设计 249
22.1.1泛型数据交换函数 249
22.1.2泛型数据比较函数 250
22.2泛型排序 251
22.2.1qsort函数 251
22.2.2泛型冒泡排序 253
22.3用指针数组实现字符串排序 254
22.3.1基本原理 254
22.3.2比较函数设计 254
22.3.3实现字符串排序 255
22.4小结 258
第23章 变长形参列表函数的设计与使用 259
23.1变长形参列表函数 259
23.2 〈stdarg.h〉头文件 259
23.2.1 va_list变量类型 260
23.2.2 va_start()宏 260
23.2.3 va_arg()宏 260
23.2.4 va_end()宏 260
23.2.5变长形参列表函数的基本框架 261
23.3实例分析 262
23.3.1求平均值 262
23.3.2按指定格式输出数据 263
23.3.3类型格式串 264
23.4小结 266
第24章 PCRE2正则表达式第三方库 267
24.1简介 267
24.2第三方库概述 267
24.2.1第三方库的构成 267
24.2.2第三方库的使用配置 268
24.3构建第三方库 268
24.3.1下载PCRE2第三方库 268
24.3.2构建PCRE2第三方库 269
24.4在Code∷Blocks中使用静态PCRE2第三方库 273
24.5在Code∷Blocks中使用动态第三方库 281
24.5.1构建动态PCRE2第三方库 282
24.5.2使用动态PCRE2第三方库 282
24.6通过Code∷Blocks的环境变量使用第三方库 285
24.7通过命令行使用第三方库 286
24.8利用“Makefile”使用第三方库 288
24.9第三方库调用方式总结 289
24.10小结 290
第25章 CGraph2D图形库 291
25.1图形库概述 291
25.1.1功能与结构 292
25.1.2坐标系统与函数命名 292
25.2图形库的配置与使用 293
25.2.1配置环境变量 293
25.2.2为Code∷Blocks配置构建参数 295
25.2.3样例代码 298
25.2.4运行机制 299
25.3函数使用说明 300
25.4小结 300
后记 302