<<C 陷阱与缺陷>>读书笔记

来源:互联网 发布:淘宝详情页英文素材 编辑:程序博客网 时间:2024/06/15 07:07


    快速读了一遍<<C 陷阱与缺陷>>,书的内容简短,但是每一处陷阱与缺陷都讲的非常清楚,也让自己产生了共鸣,有一些恰恰是自己在编码调试过程中遇到过的问题。
    <<C 陷阱与缺陷>>让我去思考,让我加深了对C语言的理解,是一本值得时常翻阅的好书。

   下面为自己的一些读书笔记:
 
    Chapter 1 词法“陷阱”
1. 词法分析中的“贪心发”:编译器将程序分解成符号的方法是,从左到右一个字符一个字符的读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号。这个处理策略有时被称为“贪心法”。
2. 字符:用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列之。因此,对于采用ASCII字符集的编译器而言,‘a’的含义与0141(八进制)或者97(十进制)严格一致。
字符串:用双引号引起的字符串,代表的却是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制为零的字符‘\0’初始化。
3. a+++++b
根据“贪心法”解析出的结果为((a++)++)+b; 但是a++不能作为左值,所以解析出的结果为(a++)+(++b)。

    Chapter 2 语法“陷阱”
1.  (*(void(*)())0)(); 解读:
    1). void(*)();  表示一个指向返回值为浮点类型的函数的指针;
    2). (void(*)()); 表示一个“指向返回值为浮点类型的函数的指针”的类型转换符。
    3). (void(*)())0 ; 表示将常数0转型为“指向返回值为浮点类型的函数的指针”。
    4). (*(void(*)())0)(); 表示调用存储位置为0的函数。
2. 使用bypedef简化表述:
    Typedef void(*funcptr)();
    ((*funcptr)0)0;
3. switch语句:
    缺点:程序员很容易遗漏各个case部分的break语句,造成一些难以理解的程序行为;
    优点:如果程序员有意略去一个break语句,则可以表达出一些采用其它方式很难方便地加以实现的程序控制结构。

    Chapter 3 语义“陷阱”
1. 许多程序设计语言中都内建有索引运算,在C语言中索引运算是以指针算术的形式来定义的。
2. 给一个指针加上一个整数,与给该指针的二进制加上同样的整数,两者的含义截然不同。如果ip指向一个整数,那么ip+1指向的是计算机内存中的下一个整数,在大多数现代计算机中,它都不同于ip所指向地址的下一个内存位置。
   [ip必须指向的是内建类型,当+1时才会指向下一个内存位置]
3. 复制指针并不是同时复制指针所指向的数据。
4. 对于像C语言这样的数组下标从0开始的语言,不对称边界给程序设计带来的便利 明显;这种数组的上界恰是数组元素的个数。
   [比如int a[10]; 数组下界为0,上界为10]
5. 数组中实际不存在“溢界”元素的地址位于数组所占内存之后,这个地址可以用于进行赋值和比较。当然,如果要引用该元素,那就是非法的了。
   [数组边界(上界)地址可以用来比较,但是其指向的值非法]
6. C语言中只有4个运算符(&&,||,?:/,,)存在规定的求值顺序。
7. 如果一个程序的main函数并不返回任何值,那么有可能执行失败。

    Chapter 4 连接
1. 连接器的输入是一组目标模块和库文件。连接器的输出是一个载入模块。
2. 我们可以在多个源文件中定义同名的函数g, 只要所有的函数g都被定义为static,或者仅仅只有其中一个函数g不是static。
3. 如果一个函数在被定义或声明之前被调用,那么它的返回类型就默认为整型。

    Chapter 5 库函数
1. 为了保持与过去不能同时进行读写操作的程序的向下兼容性,一个输入操作不能随后直接紧跟一个输出操作,反之亦然。如果要同时进行输入和输出操作,必须在其中插入fseek函数的调用。
2. 信号非常复杂棘手,而且具有一些从本质上而言不可抑止的特性。解决这个问题我们最好采用“守势”,让signal处理函数尽可能地简单,并将它们组织在一起。

    Chapter 6 预处理器
1. 混用宏和递增运算符,会使代码产生错误。
2. 宏展开可能产生非常庞大的表达式,占用的空间远远超过了编程者所期望的空间。
   [对宏的使用要谨慎,往往展开的结果与想象中的不一样。]

    Chapter 7 可移植性缺陷
1. 标准库的变更。
    [已经有ANSI C标准]
2. 标识符名称的限制。
   [已经支持大小写]
3. 如果编程者关注一个最高位是1的字符期数值究竟是正还是负,可以将这个字符声明为无符号字符 (unsigned char)。
   [负数的除法运算还需要注意]
4. 在所有的C程序中,无用null指针的效果都是未定义的。
5. 使用函数还是宏?由使用者在速度与方便之间自由选择。
6. 努力提高软件的可移植性,实际上是延长了软件的生命周期。

    Chapter 8 建议与答案
1. 在调试程序很长时间之后,疲惫不堪的程序员开始漫无目的的地瞎碰,这里试一下,那里改一点,如果凑巧程序似乎可以运行了,便万事大吉。这种工作方式往往最后导致一场灾难。


0 0
原创粉丝点击