我想拓宽我在编译器编写方面的知识和技能,尤其是优化。我想知道对于带有字符串类型的case表达式的case语句有哪些优化可用。例如,在Object Pascal中:
ReadLn(s);
case s of
'abc','def': ...;
'xyz' : ...;
otherwise ...;
end;
在Free Pascal中,这被转换为AnsiCompareText的后续调用。其他语言实现怎么样?我知道至少PHP,Nimrod和Octave支持这个。
答案 0 :(得分:0)
作为应用程序开发人员,我希望将最有可能首先执行的案例放在首位,以限制比较次数。不幸的是,从编译器的角度来看,直到运行时才会知道它。
如果我正在编写自己的编译器并遇到如上所述的case语句,我可能会尝试对比较进行排序并进行二分查找以确定要采用的路径。这有望改善最坏情况。
答案 1 :(得分:0)
在C中,char数组(字符串)没有“case”等价,但是可以使用位移宏和切换情况在某种程度上完成
#define FIVE_CHARS(c1,c2,c3,c4,c5) (((((((((c5)<<7)|(c4))<<6)|(c3))<<6)|(c2))<<6)|(c1))
while (argc-->0){
switch ( FIVE_CHARS(argv[argc][0],argv[argc][1],argv[argc][2],argv[argc][3],argv[argc][4]) ){
case FIVE_CHARS('-','h','e','l','p') :
case FIVE_CHARS('-','-','h','e','l') :
case FIVE_CHARS('-','h','\0','\0','\0') :
case FIVE_CHARS('-','?','\0','\0','\0') :
usage();
break;
case FIVE_CHARS('-','a','r','g','1') :
setflag1();
break;
default:
assert("Argument not supported");
}
}
编译器可以将其编译为具有少量比较的一系列if或具有大数字的跳转表。这可以在代码大小和速度方面提供显着的改进,因为大多数位移位(在case语句中的位移)是在编译时而不是运行时完成的,剩余的位移操作(交换机中的那个)相对便宜并且单个比较只需要一次(基本上不需要先放置最常见的路径)...对于匹配五个字符的情况,你可以为一个不常见的字符/字符添加一个额外的开关盒,或者只使用一个strcmp()。 ..但更好的是只需要几个案例的strcmp,而不是strcmp(){}的大型嵌套树,否则strcmp(){} else ...