这本书适合没事的时候翻翻,随便打开哪一页,应该都可以看下去的。总体来说,写的比较欢脱,不像《C和指针》和《C陷阱和缺陷》的章节标题那么严肃,有时候还以为自己在看科技杂志。不过,理解书里面的内容反而需要有较高的C语言基础,内容结构比较松散,如果觉得没有逻辑性,可能是语言基础还掌握的不够。
第1章 C:穿越时空的迷雾
- C语言的史前阶段:BCPL->B->New B->早期C
- C语言的早期体验(评:历史原因造成了现在C语言的一些语言特性)
- 标准I/O库和C预处理器
- K&R C ——Kernighan 和 Ritchie
- 今日之ANSI C
- 它很棒,但符合标准吗:不可移植代码,坏代码,可移植代码
- 编译限制,ANSI C标准对一个能够成功编译的程序的最小长度做了限制
- ANSI C标准的结构,与K&R C相比,最重要的新特性就是原型,这种特性取自C++。
( 原型:把形参的类型作为函数声明的一部分。这样不仅函数名和返回类型已知,所有形参类型也已知。)
不可移植的代码:由编译器设计者决定采取何种行动(即不同编译器所采取的行为可能不相同,但都是正确的)
——
未确定的
(
附:一个程序有可能在一个特定的编译器里是遵循标准的,但在另一个编译器里却是不遵循标准的。
)
坏代码
:在某些不正常的情况下,并未规定应该怎样做(即你可以采取任何行动:什么都不做、发出一条警告信息,中止程序)——
未定义的
(
附:
约束条件:一个必须遵守的限制或要求。如果不遵守,程序就会变成未定义的。
)
第2章 这不是Bug,而是语言特性
- 编程语言的细节,Fortran语言经典错误,DO 10 I=1.10和DO 10 I=1,10的区别。
分析编程语言缺陷的一种方法是把所有的缺陷归类为3类:不该做的做了,该做的没做,该做但做的不合适。
- 多做之过
- switch语句中的fall through
- 相邻字符串常量被自动合并
- 太多的缺省可见性,即默认的函数作用域过宽
- 误做之过,语言中有误导性质或是不适当的特性
- 重载,许多符号甚至关键字被重载
- 有些运算符的优先级是错误的(ANSI C标准由于种种历史原因,没有在优先级方面采取措施)
- 少做之过,语言应该提供但未能提供的特性
- 空格问题
- 注释风格
- 编译器日期被破坏
- lint程序绝不应该被分离出来,lint程序寻找bug,早用,勤用
第3章 分析C语言的声明
- 只有编译器才会喜欢的语言,声明
- 声明如何形成,至少一个类型说明符+有且只有一个声明器+零个或更多声明器+一个分号
- 优先级规则,括号内的->后缀操作符->前缀操作符,按照这个顺序优先级从高到低
- 通过图表分析C语言声明
- typedef可以成为你的朋友,为一种类型引入新名字,而不是为变量分配内存
- typedef int x[10]和#define x int[10]的区别
- 可以用其他类型说明对宏类型名进行扩展
#define
peach int
unsigned peach i;
/*
没问题
*/
typedef
int
banana;
unsigned banana i;
/*
错误,非法
*/
-
- 连续几个变量声明中,typedef保证所有变量为同一种类,#define定义则无法保证
- typedef struct foo {..foo;}的含义,不同的命名空间内使用同一个名字,bad habit
第4章 令人震惊的事实,数组和指针并不相同
- 数组并非指针
- 我的代码无法运行
-
/* file 1 */ int mango [ 100 ];/* file 2 */ extern int *mango;
- 什么是声明,什么是定义
- 声明,描述其他地方创建的对象
- 定义,确定对象类型并为其分配内存,只能出现在一个地方
- 使声明和定义匹配,指针的外部声明与数组不匹配,代码当然没办法运行
- 指针和数组的区别
指针 | 数组 |
保存数据的地址 | 保存数据 |
间接访问数据,首先取指针内容,把它作为地址,然后从这个地址取地址。如果指针有一个下标[I],就把指针的内容加上I作为地址,从中提取数据
|
直接访问数据,a[I]只是简单的以a+I为地址取得数据 |
通常用于动态数据结构 | 通常用于存储固定数目且数据类型相同的元素 |
相关的函数为malloc().free() | 隐式分配和删除 |
通常指向匿名数据 | 自身即为数据名 |