自增,自减操作符的编译过程

自增,自减操作符的编译过程

    词法分析,是指编译器把C程序中的字符处理为一个个C语言中的符号的过程。C语言中的操作符有单字符的(例如=,-,+),也有两个字符的(例如:++,--),还有更多字符的(例如类型转换操作符)。因为C语言允许两个操作符之间没有空格(例如v =+ d,其中=+为两个操作符),因此,某些字符在一起可以组成多种不同情况的操作符。例如:
    ++bbb;
    理论上,++除了可以视为前自增操作符,也可以视为两个正号操作符,等效于:
    +(+bbb);
    这个结果在语法上也是正确的。那么,C编译器是如何处理这种情况的呢?事实上,C编译器在识别代码时,遵守一种称为“贪婪法”的处理方式:“如果编译器的输入流截止至某个字符前,所有的字符都已经被解析为一个个完整的符号,那么,下一个符号将包括从该字符之后可能组成一个符号最长的字符串”。其中,所谓的“编译器的输入流”就是指程序代码。
    对于上面的++b,假定在编译器解析到第一个加号前,之前所有的程序代码都已经被正常解析,编译器将尝试向后搜寻可以组成某一符号更长的字符串。于是,编译器发现++可以组成自增操作符;继续搜寻,得到++b,这不是一个单一符号,因此,前两个加号被处理成自增操作符。这样,编译器便处理完了++。然后,编译器继续解析下一个字符b,b为一个正常字符;继续向后搜索,得到bb仍为一个正确字符;继续搜索,得到bbb仍为正确的字符;继续搜索,得到bbb;,非正常字符;因此,向后退,得到符号bbb。然后再继续解析后续的字符。
    需要注意的是,词法分析与语法分析属于两个不同的阶段。再词法分析之后,才会开始语法分析。C编译器作词法分析时不会考虑语法,不会尝试去做语法上正确的解析,只会机械地按一定规则在符号层面上处理程序代码。例如:
    +++++++b;
    按照贪婪法,分析的结果等效于:
    ++  ++  ++  +  b;
    再进行语法分析,自增操作符与加法操作符结合性为从右到左,分析结果等效于:
    ++  (++(++(+b)));
    这在语法上是错误的,编译会提示自增操作符缺少左值(1-value)。但是,如果从语法上考虑,这个语句中的字符也是可以组成正确的语句的。例如:把所有加号都视为正号操作符:
    +  +  +  +  +  +  +b;
    但是,这样做容易导致二义性。例如,语法正确的分析结果还有:
    +  +  +  +  +  (++b);
    前5个加号为正号操作符,第6个和第7个组成自增操作符。这样,编译器会产生错乱,不知该采取哪种解析结果。因此,词法分析时,编译器不会考虑语法。
    请看以下代码:

01 #include <stdio.h>
02 int main(void)
03 {
04 int a = 1;
05 int b = 1;
06
07 b = +++a; /错误/
08 b = + ++a; /正确/
09 b = ++ +a; /错误/
10 b = + + +a; /正确/
11
12 b = -++a; /正确/
13 b = -±a; /正确/
14
15 b = a++++b; /错误/
16 b = a+++ +b; /正确/
17
18 return 0;
19 }
【代码解析】

     在上述程序中,从第7~10行,语句的字符完全一样,只是其中三个加号之间的空格数有所区别。
  第7行中,三个加号连在一起,按照贪婪法,前两个加号被解析为自增操作符,第3个加号解析为正号操作符。解析效果等效于:
  b = ++ (+ a);
  在语法上,由于自增操作符与正号操作符优先级相同,因此,按照从右到左的结合性,先执行+a,再对执行的结果做自增。由于+a的值不能被赋值,因此,该语句是错误的。提示信息为:自增操作符缺少左值。
  第10行中,每两个加号之间都有一个空格,因此,三个加号都被解析为正号操作符。按照从右到左的顺序结合,该语句等效于:
  b = + ( + ( +a) );
  第12行与第13行语句的词法解析比较简单,都能得到正确的结果,分别等效于:
  b = - ( ++a );
  b = - ( + ( -a ) );
  第15行中,词法分析的等效结果为:
  b = (a++)  ++  b;
  这个语句在语法上是错误的,两个自增操作符都是后自增操作符。第一个后自增操作符的操作数为变量a,第二个后自增操作符的操作数为a++的值。因为a++不能为左值,是针对第二个操作符而发的。由于(a++)  ++是一个完整的表达式,而b也是一个完整的表达式,在它们之间必须有操作符或者分号,因此,编译器还会报告一个错误:b之前缺少分号。
  第16行中,前3个分号之间紧挨在一起,在第4个加号之间有一个空格。该语句将被解析为:
  b = (a++)  +  (+b);                                    /*第16行的等效效果*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值