第一章 词法陷阱
1.1 =不同于==
1.2 &与|不同于&&与||
1.3 词法分析中的”贪心法”
- 编译器将程序分解成符号的方法是,从左到右一个一个字符读入,如该字符能组成一个符号,再读入下一个字符.判断两个字符组成的字符串是否可能是一个符号的组成部分.如能,继续读入下一个字符.重复上述判断.
1.4 整型变量
- 注意进制 0开头:8进制
1.5 字符与字符串
- 用单引号引起的一个字符实际上是代表一个整数! 整数值对英语该字符在编译器采用的字符集中的序列值.
- 用双引号引起的字符串,代表的是一个指向无名数组起始字符的指针.
第二章 语法陷阱
2.1 理解函数声明
2.2 运算符的优先级问题
- 类型转换也是单目运算符
- 条件运算符是三目运算符
2.3 注意作为语句结束标志的分号
2.4 switch语句
- break
2.5 函数调用
- 若f是一个函数
- f(); // 调用函数语句
- f; // 函数f的地址!
2.6 “悬挂”else引发的问题
- 注意
// 大括号写
if(){
//…
}
else{
//…
}
第三章 语义陷阱
3.1 指针与数组
- C语言中只有一维数组,而且数组大小必须在编译阶段作为一个常数确定.
- 任何指针都是指向某种类型的变量!
- siseof(a) //a是一个数组,结果是整个数组a的大小,而非指向数组a的元素的指针的大小.
3.2 非数组的指针
- 在C语言中,字符串常量代表了一块包括了字符串中所有字符已经I一个空字符’\0’的内存区域的地址.
3.3 作为参数的数组声明
- 将数组作为函数参数毫无意义! C语言中会自动将作为参数的数组声明转换为相应的指针声明!
3.4 避免”举隅法”
- synecdoche: 用宽泛的词语来代替相对较窄的词语..
- 指针及地址啊!
char *p,*q;
p=”xyz”;
//p的值是’x”y”z”\0’组成的数组的起始元素的指针
3.5 空指针并非空字符串
- 编译器保证由 0 转换而来的指针不等于任何有效的指针.
#define NULL 0
3.6 边界计算与不对称边界
- 在C语言中,一个拥有n个元素的数组,它的元素下标从0到n-1
3.7 求值顺序
3.8 运算符&& || !
3.9 整数溢出
- 无符号数,没有所谓的”溢出”一说?
- 有符号数,”可能”发生”溢出”
- INT_MAX
3.10 为函数main提供返回值
第四章 链接
4.1 什么是链接器
- 分别编译: 编译器一般每次只处理一个文件..所以不能检出那些需要一次了解多个源程序文件才能察觉的错误..
- 典型的链接器把由编译器or汇编器生成的若干个目标模块,整合成一个被称为载入模块or可执行文件的实体..
- 链接器的一个重要工作就是处理命名冲突..
- C语言实现中提供了 lint 程序
4.2 声明与定义
4.3 命名冲突与static修饰符
- static修饰符是一个能够减少命名冲突的有用工具..
static int a;
// 其含义与下面的语句相同
int a;
// 只不过a的作用域限制在一个源文件中,对于其他源文件,a是不可见的.
// static不仅适用于变量,也适用于函数
4.4 形参 实参与返回值
4.5 检查外部变量
4.6 头文件
库文件
5.1 返回整型的getchar函数
- 有关库文件的使用,最好的建议:尽量使用系统头文件.
5.2 更新顺序文件
5.3 缓冲输出与内存分配
- 当一个程序生成输出时,是否有必要将输出立即展示给用户? 程序输出有两种方式.一种是即时处理方式.另一种是先暂存起来..然后大写写入的方式..
5.4 使用error检测错误
5.5 库函数signal
第六章 预处理器
- 需要将某个特定数量 在程序中同一修改
- 大多数C语言实现在函数调用时,会带来大量系统开销.
6.1 不能忽视宏定义的空格
6.2 宏并不是函数
- 最好在宏定义中把每个参数都用括号括起来,同样,整个结果表达式也应该括起来.以防止宏用于一个更大一些的表达式中出现问题.
6.3 宏并不是语句
6.4 宏并不是类型定义
第七章 可移植性缺陷
7.1 应对C语言标准变更
7.2 标识符名称的限制
7.3 整数的大小
- C语言中提供了3中不同长度的整数: shrot int long
- 三种类型的整数其长度非递减.
- 一个普通(int类型)整数足够容纳任何数组的下标
- 字符长度由硬件特性决定!!!
- typedef关键字
7.4 字符是有符号整数还是无符号整数
7.5 移位运算符
7.6 内存位置0
- null指针并指向任何对象
- 在所有C程序中,误用null指针的效果都是未定义的.
7.7 出发运算发生的截断
7.8 随机数的大小
7.9 大小写转换
- 库函数 toupper 和 tolower
7.10 首先释放,然后重新分配
- C语言提供了3个内存分配函数: malloc realloc free
第八章 建议
最重要的技巧是 知道自己在做什么!!!
对程序的组合方式的理解非常重要!!!
8.1 建议
- 不要说服自己相信”皇帝的新衣”
- 直接了当地表明意图
- 考察最简单的特列
- 使用不对称边界
- 注意潜伏在暗处的bug
坚持只使用C语言众所周知的部分..避免使用生僻语言特性 - 防御性编程