编译原理中讲到程序构造的一般过程是:词法分析、语法分析、语义分析、中间代码生成、代码优化和目标代码生成。词法分析对应的就是C语言中的“单词”(也称“符号”),指的是程序的一个基本组成单元,每个符号都有自己固定的字符序列,但是同一个字符序列可能属于不同的符号。
例如:字符序列“->”,有可能代表的是->运算符,也有可能代表字符串“->”,这就需要根据上下文环境判断。
1、C语言中符号之间的空白(空格、制表符或换行符)都被忽略
if(1<x)
if
(
1
<
x
)
这两条语句是等效的,注意这里指的是“符号之间”的空白,不是“符号之内”,如果把“if”写成“i f”是不行的,"if"在C语言内部是一个固定的符号,是可以识别的有效“单词”,而“i f”却不是,可以拿英文句子来类比分析。“I am the best!”是一个有效语句,是因为在词法分析时各个单词都是有效单词;如果写成“I am the best!”,仍然有效;但是“I am the b est !”无效,因为“b est”在系统库中无法找到匹配的单词,道理相同。
2、C语言中符号之内不能有空白(空格、制表符或换行符)
编译器区分各个符号的终极原则就是“空白”(还有其他原则,例如贪心法),如果符号之内有空白,编译器只能(也是必须)把它们解释成“两个或多个符号”,如果没有空白,也可能解释成多个符号,这时贪心法在起作用。例如:++是一个“自增运算符”,+ + 就是两个“加法运算符”,+++虽然没有空白,也只能解释成“自增运算符+加法运算符”,因为贪心法在作怪。
3、“符号之间”和“符号之内”的讨论,有什么用处?
我们编写程序,首先是给人读懂,其次是给计算机(也可认为编译器)读懂,两者缺一不可。如果“人”和“计算机”对同一个事物的理解出现偏差,那运行结果就不可预料了,而今天的讨论就是为了让我们更加“懂计算机”,理解“计算机”的思维方式,在“人”读懂的基础上,让“计算机”也能读懂,甚至必要时以“计算机”读懂为根本方针。
词法分析中的“贪心法”:编译器在对符号进行分解时,必须对某个“连续字符串”进行顺序分析(不连续的字符串,肯定不属于同一个“符号”,直接截断并对每个片段单独用贪心法分析),确定由几个符号(单词)组成。确定符号的过程中,编译器假设每个符号包含尽可能多的字符(字母),即:从字符偏移0开始依次读取字符串,如果加上下一个字符还能组成一个有效的符号就加上它,持续添加直到加上某个字符后,就不再是一个有效符号了,那么这个字符前面的从偏移0开始的字符串,就是一个有效的“符号”;继续修改偏移0到这个字符,持续上述过程知道本行结束。
理解了“贪心法”,我们在程序书写上就应该尽量照顾计算机的思想,而不是随便写一通。例如:
result = num/*p;
对这行代码,计算机用贪心法分析符号有6个“result、=、num、/*、p、;”,而我们的理解是“result 、=、num、/、*p、;”。本来想写一个除法表达式,num除以指针p指向的内容,可是计算机理解成了“result = num”剩下的是注释,显然不是我们想要的。如何切断贪心法对"/*"的连接呢?根据上面的讨论,我们用“空格”,写出这样:
result = num/ *p;
当增加一个空格后,贪心法再次分析到“/”的时候,由于后边紧跟空格不再是连续字符串,所以无条件截断,这样就可以防止上面的情况发生。还可以用括号进行显式指定:
result = num / (*p) ;
这一次既对代码进行了手动空格分割,便于计算机理解,又添加了括号,增加了代码的可读性。真正高质量的代码就是这样,计算机阅读没有二义性,人阅读也没有二义性。所以代码中,要善于利用空格和括号,提高规范性提升代码质量,防止歧义发生。
靠谱推荐:Free Pos,微信JOCIHEZ