AndrewKoenig自己在Bell实验室时发表的论文为基础,结合自己的工作经验扩展成这本对C程序员具有珍贵价值的经典著作。写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过编程过程中的陷阱和障碍。
本书所揭示的知识,至少能够帮助你减少C代码和初级C++代码中90%的Bug!!!
下面是博主看完后整理的。(禁止抄袭,违者必究法律责任!)这是第一大篇,共三篇。
@[目录]
1词法分析中的贪心法 2字符与字符串
3理解函数声明 4运算符优先级
5语句结束标志 6函数调用
7悬挂else引发的问题 8数组与指针
9非数组指针 10作为参数的数组声明
11避免“举偶法 12空指针并非空字符串
13边界计算与不对称边界 14整数溢出
15为main函数提供返回值
词法分析中的贪心法
首先,C语言有单字符符号,如 / 、* 、=,和多字符符号,如==、+=。那么当C编译器读入一个字符 ’/‘ 后又有一个 ’‘ ,编译器会以一个规则进行分析:每一个符号应该包含尽可能多的字符,所以 / 同时出现时会被当做一个符号 ’/*‘ ,而不是两个单独的符号。也就是说,编译器从左到右一个一个地读取字符,直到所读取的字符和前一个符号所包含的字符不能构成一个有意义的字符时,前一个字符到此前结束。
举个例子:(按规则分析)
本意是x除以p所指向的值,再把商赋值给y。显然下面这个例子会被当成y=x进行处理。
y=x/*p;
可以修改为:
y=x / *p;//注意空格
//或者
y=x/(*p);
再举一个例子: c语言n–>0的含义是 n-- >0 , 而不是 n- -> 0。
需要注意的是,除了字符串和字符常量,符号中间不能有空白(空格符、制表符、换行符)。
比如: a+++++b在编译时会报错,而(a++)+(++b)和a++ + ++b不会报错。
字符与字符串
在C语言中,字符串常量代表一块包括字符串中所有字符以及一个空字符的内存区域的地址。由此对于其他字符串,也沿用这一惯例。
单引号括起的一个字符代表一个整数,而双引号括起的一个字符代表一个指针。要避免两者混用。
举个例子:
char *p='/';
这个在编译时会出现错误,因为’/‘ 并不是一个字符指针。然而,C编译器对函数的参数,尤其是printf 的函数参数不做类型检查,在程序运行时就会产生难以预料的错误,而且编译器不会给出任何错误。
举个例子:
printf('\n');
printf("\n");
当然,现在编译器一般能检测到函数在调用时混用单引号和双引号的情况。
理解函数声明
任何C变量的声明都·由两部分组成:类型及一组类似的表达式的声明符。
举个例子:
float *g(), (*h)();
表示* g() 与(*h)() 的浮点表达式。因为() 优先级高于 * ,g() 也就是(g()),g是一个函数,该函数的返回值类型为指向浮点数的指针。而h是一个函数指针,所指向函数的返回值为浮点类型。
一旦我们知道如何声明一个给定类型的变量,那么该类型的类型转换符就很容易得到:只需把声明中的变量名和末尾的分号去掉,再将剩余部分用一个括号封装起立即可。
举个例子:
float (h)();h 表示一个指向返回值为浮点类型的函数的指针,则 float ()() 表示一个指向返回值为浮点类型的函数的指针的类型转换符。
运算符优先级
任何一个逻辑运算符的优先级低于任何一个关系运算符; 移位运算符的优先级比算数运算符低,但比关系运算符高。
语句结束标志
①下面这两段代码一样:
if (x[i]> s);
s=x[i];
if(x[i]>s