读书笔记之:C陷阱与缺陷

C陷阱与缺陷


词法”陷阱“
= 不同于 ==:=:赋值运算;==:作为比较;
& 和 | 不同于 && 和 || :& 和 | :按位运算符;&& 和 || 逻辑运算符; 
词法分析中的“贪心法”;
整型常量;
字符与字符串;‘’代表一个整数 和 “”代表一个指针 ;


语法“陷阱”:
理解函数声明;
运算符的优先级问题;记住C语言中运算符的优先级是有益的。
注意作为语句结束标志的分号;
函数调用;
“悬挂”else引发的问题;


语义“陷阱”:
指针与数组:
1、C语言中只有一维数组,而且数组的大小必须在编译期就作为常数确定下来;(C99标准允许变长数组);
2、对于一个数组,我们只能够做两件事:确定该数组的大小,以及获得指向该数组下标为0的元素的指针;
非数组的指针:
作为参数的数组声明:
避免“举隅法”:混淆指针与指针指向的数据;
复制指针并不同时复制指针所指向的数据;

空指针并非空字符串:
编译器保证由0转换而来的指针不等于任何有效的指针。
边界计算与不队称边界:
C语言中拥有n个元素的数组,却不存在下标为n的元素,它的元素的下标范围从0~n-1;
求值顺序:
运算符&&、||和!:
整数溢出:
为函数main提供返回值:


连接:
一个C程序可能是由多个分别编译的部分组成,这些不同部分通过一个通常叫做连接器(也叫连接编辑器,或载入器)的
程序合并成一个整体;
连接器的输入是一组目标模块和库文件。连接器的输出是一个载入模块;
声明与定义:
要想在所有的C语言实现中避免多重定义问题,唯一的解决办法就是每个外部变量只定义一次;
命名冲突和static修饰符:
为了避免可能出现的命名冲突,如果一个函数仅仅被同一个源文件中的其他函数调用,我们就应该声明该函数为static。
形参、实参、返回值:

检查外部类型:
头文件:
每个外部对象只在一个地方声明。这个声明的地方一般就在一个头文件中,需要用到该外部对象的所有模块都应该包括这个头文件;
特别需要指出的是,定义该外部对象的模块也应该包括这个头文件。

库函数:
返回整数的getchar函数;
更新顺序文件;
缓冲输出与内存分配:
使用errno检测错误:
库函数signal:


预处理器:
不能忽视宏定义中的空格:
宏并不是函数;
宏并不是语句;
宏并不是类型定义;

可移植性缺陷:
应对C语言标准变更:
标识符名称的限制;
整数的大小;
1、short < int < long;
2、一个普通(int)类型整数足够大以容纳任何数组下标;
3、字符长度由硬件特性决定;
字符是有符号整数还是无符号整数;
移位运算符:
内存位置0;
除法运算时发生的截断;
随机数的大小;
大小写转换:
首先释放,然后重新分配;

建议:
最重要的规避技巧就是,知道自己在做什么。
不要说服自己相信“皇帝的新装”
直截了当地表明意图;
考察最简单的特例,从最简单的特例获得启发;
使用不对称边界;
注意潜伏在暗处的Bug;
防御性编程;

猜你喜欢

转载自blog.csdn.net/cheatscat/article/details/80480324