本书的介绍
作者以自己1985年在Bell实验室时发表的一篇论文为基础,结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作。写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过编程过程中的陷阱和障碍。
全书分为8章,分别从词法分析、语法语义、连接、库函数、预处理器、可移植性缺陷等几个方面分析了C编程中可能遇到的问题。最后,作者用一章的篇幅给出了若干具有实用价值的建议。
本书适合有一定经验的C程序员阅读学习,即便你是C编程高手,本书也应该成为你的案头必备书籍。
前言
N年读过这本书,当时读的时候囫囵吞枣,加上时间久远,90%的内容都忘记了。昨天在整理书籍的时候翻出来了,这本书短小精悍却不失为经典之作。抽出时间再拜读一遍,顺便做做笔记,记录精华。
第一章,词法“陷阱”
1.1 =不同于==
c语言中”=”是赋值运算符
“==”是关系运算符,用于两个数进行比较
1.2 & 和 | 不同于&& 和 ||
&:按位与,优先级高于&&
|:按位或,优先级高于||
&&:逻辑与
||:逻辑或
1.3 词法分析中的“贪心法”
原文是这么说的:如果编译器输入流截止某个字符之前都已经被分解为一个个符号,那么下一个符号将包括从该字符之后可能组成一个符号的最长字符串。
例子:==被编译器解析为一个比较符号,而= =被编译器解释为两个赋值符号
a=b/*p;本意是a=b/(*p),但*被编译器解释为注释的开始符号,要么写成a=b/ *p或者a=b/(*p)
1.4 整型常量
在C/C++中,表示8进制整数需要在最前面加0,如0122
在表示十进制的地方,不要用0进行文本格式的对齐。
1.5 字符与字符串
单引号中的字符被编译器视为一个整数,不管单引号中有几个字符,比如’a’和’abcd’都被视为整数。
unsigned int value1 = 'tag1';
unsigned int value2 = 'cd';
char value3 = 'abcd';
在vs2013编译上述代码后各个变量结果如下:
value1= 't'<<24 | 'a'<<16 | 'g'<<8 | '1'=0x74616731
value2= 'c'<<8 | 'd'=0x00006364
value3='d'=0x64
可以用多个字符给value3赋值,但value3仅保留最后一个字符的值。
对于value1和value2,赋值时最多传入四个字符,可以少于4个字符,否则编译器会报错。
第2章 语法“陷阱”
2.1 理解函数声明
这一节主要讲的是函数指针的声明、定义和使用。
void (*pFunc)();
typedef void (*pFunc)(); 相当于定义了一个数据类型pFunc,这个数据类型是函数指针类型,这个类型是void (*)();
pFunc f;
使用f的方式如下:
(*f)(); ANSI C标准允许进行简写,简化为 f();
注意,上面的调用方式不能写成下面的形式:
*f(); 由于括号的优先级最高,所以这种方式实际变成*(f());
*f; 只计算出一个整数值,并未进行函数调用;
f; 只计算出一个整数值,并未进行函数调用;
2.2 运算符的优先级问题
在编程中要特别注意运算符的优先级。
运算符的优先级可以利用口诀进行记忆,即“单算移关与,异或逻条赋”
■“单”表示单目运算符:逻辑非(!),按位取反(~),自增(++),自减(–),取地址(&),取值(*);
■“算”表示算术运算符:乘、除和求余(*,/,%)级别高于加减(+,-);
■“移”表示按位左移(<<)和位右移(>>);
■“