C编译器剖析_5.3.2 中间代码生成及优化_switch语句的翻译

本文详细介绍了C编译器如何处理switch语句,包括switch语句的翻译过程、中间代码生成以及针对不同情况的优化策略。编译器在处理switch语句时,会考虑case语句的密度,通过跳转表技术来提高执行效率,同时在遇到大量case语句时,使用二分查找方法降低比较次数。此外,文章还提及了break和continue语句的翻译方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

5.3.2.Switch语句的翻译

   在这一小节中,我们来讨论一下switch语句的翻译,switch语句的产生式如下所示。

SwitchStatement:

                   switch( expr ) statement

   当C程序员编写出如下代码时,UCC编译器会在语义检查阶段进行报错“error:The  break shall  appear  in  a  switch  or loop”,从语法上来看,以下“case  3: b = 30;”是case语句,而“break;”并不是case语句的一部分。按switch语句的产生式,以下“switch(a)  case 3: b = 30;”构成一条完整的switch语句,而“break;”则不在switch语句内。

         switch(a)

                   case  3:  b =30;  break;

    虽然按switch语句的产生式,其中的statement部分并不一定是复合语句,但通常C程序员在编写代码时,会将此部分写为一个复合语句,例如:

         switch(a){

                   case  3: b = 30; break;

         }       

     此时,复合语句中的“break;”就包含在swich语句中,这就可以符合C语言的语义要求,即“break语句要被包含在switch语句或者循环语句”中。到了中间代码生成阶段,我们面对的已经是“没有语法或语义错误”的语法树。我们还是举一个例子来说明switch语句的翻译,如图5.3.3所示,第4至17行为一个switch语句,与之对应的中间代码在第23至40行。我们注意到,第28行是一条“间接跳转”指令,我们根据(a-1)的值来索引跳转表“[BB4,BB8,BB6,BB12,BB10,]”,从而得到相应的跳转目标,例如当a为1时,我们得到的跳转目标为BB4,当a的值为4时,由于4并不落在{1,3,2,5}中,对应的跳转目标BB12用于跳出switch语句。通过跳转表的技术来翻译switch语句,可以使得生成的汇编代码在运行时不需要进行过多的比较,从而加快代码的执行速度,不过,跳转表本身需要占用内存空间,这是一种“以空间换时间”的方法。第44至53行是对应的部分汇编代码,第44至49行的跳转表switchTable1在数据区中,其中存放的是跳转目标的首地址(代码区中的地址),而第50至53行则根据(a-1)的值来查表,再进行跳转。


图5.3.3  switch语句的例子

    在图5.3.3的例子中,各case语句中的常量为{1,3,2,5},这些整数在数值上相差不大,如果我们遇到的是{1,2,20000,50},相应的跳转表就得有20000个表项,其中大部分的表项存放的是形如“BB12”这样的用于跳出switch语句的地址,这需要耗费相当大的内存,此时我们不再构造一张跳转表,而是想把{1,2,20000,50}分成几段,每一段内的各个数值彼此接近,例如我们可把{1,2,20000,50}分成3段{ {1,2},{50},{20000}}。我们制定一个标准,来衡量各数值彼此接近的程度,UCC编译器引入了一个“Case语句密度”的概念,

         Case语句密度 =Case语句数量/ 区间大小

    例如,对于{1,2,20000,50}来说,其密度为(4/(20000-1)),这有点像人口密度的概念,反映了人口的密集程度,而{1,2}的密度为2/(2-1)。为了方便代码生成,UCC编译器在语法分析时,会把在同一switch语句的各case语句,按出现的先后顺序进行排列。而为了统计“Case语句密度”,在语义检查时,会按各case语句的常量表达式数值,从小到大进行排列。因此,每条case语句实际上会出两个链表中,UCC编译器用结构体astCaseStatement来描述一条case语句,其中的next和nextCase域用于构造这样的两个链表。

         struct  astCaseStatement{

                  //按case语句在源代码中出现的先后顺序排列

                  struct astNode *next;    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值