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

时间:2022-04-30 17:50:29

第一章:词法陷阱

编译器中负责将程序分解为一个一个符号的部分,一般称为“词法分析器”。例如,对于语句:

if ( x == big ) big = x ;

它的第一个符号是C语言关键字if,紧接着下一个符号是左括号,在下一个符号是标识符x,在下一个是大于号,在下一个是标识符big,以此类推。在C语言中,符号之间的空白(包括空格、制表符、换行符)将被忽略,因此上面的语句还可以写成:

if

(

x

==

big

)

big

=

x

;

这里还需要强调一下“C语言忽略符号间空白”。第一:“符号”的意思并不是“字母”,例如上面的语句中的“==”和“big”,它们都包含了多个字母,但是它们从整体上是一个符号,不可分割。第二:忽略符号与符号之间的空白,意即经过编译器的词法分析之后,符号与符号之间的空白不会被作为一个符号。但是,请注意的是,第二点并不意味着可以乱用空格,例如,在上面的语句中,“==”不可以写做“= =”,如果写成后者,便成了两个赋值号,程序的意思也就变了。

1.1 = 不同于 ==

前者是赋值,后者是判断相等,对于C语言初学者,很容易就犯误用的错误。

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

前两者是位运算,后两者是关系运算。

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

C语言中的某些符号,例如/、*、和=,只有一个字符,称为单字符符号。而C语言中的其他符号,例如/*和==,以及标识符,包括了多个字符,称为多字符符号。那么当C语言的编译器的词法分析模块读入了一个字符‘/’后又跟了一个字符‘*’,那么编译器就必须做出判断:是将其作为两个分别的符号对待,还是合起来作为一个符号对待。C语言解决这个问题的方案很简单,那就是“贪心法”:每一个符号应该包含尽可能多的字符。

需要注意的是,除了字符串和字符常量,符号的中间不能嵌有空白(空格符、制表符和换行符)。例如,“==”是单个符号,而“= =”则是两个符号。例如下面的表达式:

a---b

那么按照“贪心法”,它的含义是:

(a--) - b

而:

a- --b

的含义是:

a - (--b)

再例如下面的语句,本意似乎是用x除以p所指向的值,把所得的商再赋值给y:

y = x/*p  /* p指向除数*/

而实际上,因为“贪心法”,上面语句中的x后面的/*会被C语言词法分析器理解为一段注释的开始。

正确的表达当如下:

y = x/ *p  /* p指向除数*/

或者更清楚一点:

y = x/(*p) /* p指向除数*/

1.4整型常量

021不同于21,前者是八进制,后者是十进制。

练习1-1 写一个测试程序,无论是对于允许嵌套注释的编译器还是对不允许嵌套注释的编译器,该程序都能够正常通过编译,但是两种情况下程序的执行结果却不相同。

答案: /*/*/0*/**/1

在允许嵌套注释的情况下,上式值为1;

在不允许嵌套注释的情况下,上式值为0*1;