C陷阱与缺陷 —— 读书笔记-1、词法“陷阱”

《C陷阱与缺陷》是由Andrew Koenig所著,高巍译。Andrew Koenig是AT&T大规模程序研发部(前贝尔实验室)成员,不仅有着多年的C++开发,研究和教学经验,而且还亲身参与了C++的演化和变革,对C++的变化和发展起到重要的影响。

第一章    词法陷阱

编译器中负责将程序分解为一个一个符号的部分,一般称为“语法分析器”。

1.1    = 不同于 ==

while
(c=‘‘ || c==‘ ‘ || c==‘ ‘)

c=getc(f);

这个循环将一直进行到文件的结束,是否死循环取决于getc的实现。

如果确实需要在条件判断部分使用赋值,应该显式地进行比较:

if
((x=y) != 0)

foo();

 1.2
   & 和 | 不同于 && 和 ||

 1.3
   语法分析中的“贪心法”

C语言对这个问题的解决方案可以归纳为一个很简单的规则:每一个符号应该包含尽可能多的字符。

编译器将程序分解成符号的方法是,从左到右一个字符一个字符地读入,如果该字符可能组成一个符号,再接着读下个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分;如果可能,继续读入下一个字符,重复上述判断,知道读入的字符组成的字符串已不再可能组成一个有意义的符号。这种处理策略有时被称为“贪心法”,或者更口语化一点,称为“大嘴法”。

a---b
与 a --  - b 的含义相同,而与  a -   -- b 的含义不同。

1.4    整型常量

如果一个整型常量的第一个字符是数字0,那么该常量将被视作八进制数。

1.5    字符与字符串

C语言中的单引号和双引号含义迥异,在某些情况下如果把两者弄混,编译器并不会检测报错,从而在运行是产生难以预料的结果。

用单引号引起的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。

用双引号引起的字符串,代表的却是一个指向无名数字起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制为零的字符 ‘\0‘ 初始化。

然而,某些C编译器对函数参数并不进行类型检查,特别是对printf函数的参数。因此, 如果用

printf(‘ ‘);        来代替正确的     printf(" ");

则会在程序运行的时候产生难以预料的错误,而不会给出编译器诊断信息。

整型数(一般为16位或32为)的存储空间可以容纳多个字符(一般为8位),因此有个C编译器允许在一个字符常量(以及字符串常量)中包括多个字符。也就是说,用‘yes‘代替"yes"不会被该编译器检测到。后者的含义是“一次包括‘y‘‘e‘‘s‘以及空字符‘‘的4个连续内存单元的首地址“。前者的含义并没有准确的进行定义,但大多数编译器理解为,“一个整数值,由‘y‘‘e‘‘s‘所代表的整数值按照特定编译器实现中定义的方式组合得到“。

习题:

练习  1-3  为什么 n-- > 0, 而不是 n-  ->0?

答:根据词法分析中的“贪心法”,编译器在读取字符的顺序是先读取n ,然后读取 - ,在读取 -,判断出n--组成字符串是一个符号,再读取> 时,不能组成符号,故是n--
> 0, 而不是 n-  ->0,注意--之间不能嵌有空白、空格符、制表符和换行符。)

练习  1-4
 a+++++b的含义是什么?

答:根据贪婪法匹配原则,它的含义应为  a++
 ++  +b,而不是a++  +  ++b(可能是合法的)考虑。这是个非法的表达式,因此产生编译错误。这个问题在ISO C99标准中直接以示例描述,原文如下:

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-13 15:28:52

C陷阱与缺陷 —— 读书笔记-1、词法“陷阱”的相关文章

C陷阱与缺陷 读书笔记

C陷阱与缺陷 1.  typedef用法: ①    定义一种类型别名,而不是简单的宏替换: char *pa,pb;(注意:pb并没有定义为指针,虽然你可能想这么定义它) typedef char* PCHAR PCHAR pa, pb; ②   用在旧的C代码中,帮助struct.以前的代码中,声明struct新对象时,必须带上struct,即形式为:struc结构名对象名,如: struct tagPOINT1 { Int x; Int y; }; struct tagPOINT1 p1;

C陷阱与缺陷学习笔记

本书的介绍 作者以自己1985年在Bell实验室时发表的一篇论文为基础,结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作.写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过编程过程中的陷阱和障碍. 全书分为8章,分别从词法分析.语法语义.连接.库函数.预处理器.可移植性缺陷等几个方面分析了C编程中可能遇到的问题.最后,作者用一章的篇幅给出了若干具有实用价值的建议. 本书适合有一定经验的C程序员阅读学习,即便你是C编程高手,本书也应该成为你的案头必备书籍. 前言 N年读过这本书

[C陷阱和缺陷] 第2章 语法“陷阱”

第2章 语法陷阱 2.1 理解函数声明 当计算机启动时,硬件将调用首地址为0位置的子例程,为了模拟开机时的情形,必须设计出一个C语言,以显示调用该子例程,经过一段时间的思考,得出语句如下: ( (void() () )0 ) (); 像这样的表达式看起来很难理解,但只要将其一层一层地剥离,还是能够理解的.下面我将用几个例子来帮助大家逐渐理解这个表达式. void *a(); void (*b) (); 因为()的优先级高于*,所以*a()为*(a()),a是一个函数,该函数的返回类型为void*

读书笔记--C陷阱与缺陷(七)

第七章 1.null指针并不指向任何对象,所以只用于赋值和比较运算,其他使用目的都是非法的. 误用null指针的后果是未定义的,根据编译器各异. 有的编译器对内存位置0只读,有的可读写. 书中给出了一种判断编译器如何处理内存0的代码: 1 #include <stdio.h> 2 int main() 3 { 4 5 char *p; 6 p=NULL; 7 printf("location 0 contains: %d\n", *p); 8 9 return 0; 10

《C陷阱与缺陷》读书笔记

<C陷阱与缺陷>读书笔记 1.编译器中的词法分析器负责将程序分解为一个个符号.C语言中,符号之间的空白 (包括Space ,Tab , Enter) 都将被忽略,但一个符号的中间不能有空白,否则可能被解释成为另一个或几个符号. 2.编译器将程序分解成符号的方法是从左到右逐个字符读入,如果该字符可能会组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分:如果可能,继续读入下一个字符,重复上述判断,直到读入的字符组成的字符串已经不再可能组成一个有意义的

读书笔记--C陷阱与缺陷

要参与C语言项目,于是作者只好重拾C语言(之前都是C++,还是C++方便). 看到大家都推荐看看  C陷阱与缺陷(C traps and pitfalls),于是好奇的开始了这本书的读书之旅. 决定将书中重要的知识点和易错点记录下来方便自己复习和他人学习~~不多说了,下面开始. 第一章:词法陷阱 在C语言中,符号(程序文字)之间的空白(包括空格符.制表符.换行符)将被忽略.书中举了一例: 1 if (x > big) big = x; 2 可以写成: 3 if 4 ( 5 x 6 > 7 bi

我的《C陷阱与缺陷》读书笔记

第一章 词法"陷阱" 1. =不同于== if(x = y) break; 实际上是将y赋给x,再检查x是否为0. 如果真的是这样预期,那么应该改为: if((x = y) != 0) break; 2. &和| 不同于 && 和 ||   3.词法分析中的"贪心法" 编译器将程序分解成符号的方法是:从左到有一个一个字符的读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符床是否可能是一个符号的组成部分:如

C缺陷与陷阱----读书笔记---第一章

第一章:词法陷阱 编译器中负责将程序分解为一个一个符号的部分,一般称为“词法分析器”.例如,对于语句: if ( x == big ) big = x ; 它的第一个符号是C语言关键字if,紧接着下一个符号是左括号,在下一个符号是标识符x,在下一个是大于号,在下一个是标识符big,以此类推.在C语言中,符号之间的空白(包括空格.制表符.换行符)将被忽略,因此上面的语句还可以写成: if ( x == big ) big = x ; 这里还需要强调一下“C语言忽略符号间空白”.第一:“符号”的意思

《C陷阱与缺陷》学习笔记(一)

前言和导读 "得心应手的工具在初学时的困难程度往往超过那些容易上手的工具."比较认同这句话.我至今觉得自己其实还是个刚入了门的初学者. 第一章 "词法"陷阱 由于之前学过编译原理,对编译器词法分析(主要是符号识别过程)比较了解,理解起来不困难. 在讲到"="和"=="."|"和"||"."&"和"&&"时,联想起以前见过一些