Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Compiler construction 开关大小写构造是否实现为二进制搜索?_Compiler Construction_Switch Statement - Fatal编程技术网

Compiler construction 开关大小写构造是否实现为二进制搜索?

Compiler construction 开关大小写构造是否实现为二进制搜索?,compiler-construction,switch-statement,Compiler Construction,Switch Statement,我想知道开关-案例语句是如何实现的: 示例 假设一个人有以下代码: Scanner sc = new Scanner(System.in); int v = sc.nextInt(); switch(v) { case 0 : System.out.println("Zero"); break; case 1 : System.out.println("One"); break; case 2 :

我想知道
开关
-
案例
语句是如何实现的:

示例

假设一个人有以下代码:

Scanner sc = new Scanner(System.in);
int v = sc.nextInt();
switch(v) {
    case 0 :
        System.out.println("Zero");
        break;
    case 1 :
        System.out.println("One");
        break;
    case 2 :
        System.out.println("Two");
        break;
    //...
    default :
        System.out.println("No one digit number");
}
可以通过以下方式实现这一点:

if(v == 0) {
    System.out.println("Zero");
}
else if(v == 1) {
    System.out.println("One");
}
else if(v == 2) {
    System.out.println("Two");
}
//...
else {
    System.out.println("No one digit number");
}
但更有效的方案是:

if(v >= 0 && v <= 9) {
    if(v <= 5) {
        if(v <= 2) {
            if(v <= 1) {
                if(v == 0) {
                    System.out.println("Zero");
                }
                else {
                    System.out.println("One");
                }
            else {
                System.out.println("Two");
            }
        }
        //...
    }
    //...
}
else {
    System.out.println("No one digit number");
}

如果(v>=0&&vswitch语句的实现方式取决于“case”列表。当“case”集合密集时,可以使用跳转表(如存在
goto Label[v]
语句)。这比二进制搜索快得多。

Switch/case语句使用二进制决策树和跳转表的组合来实现,具体取决于案例范围

  • 对于简单的switch语句(2-3种情况),根据值的密集程度(例如123vs129),发出简单的if语句通常更有效

  • 对于具有单个密集组的较大基数开关,通常使用直接或间接基于测试值的跳转表

  • 对于稀疏组,或密集组和稀疏组的混合,使用二叉决策树对分组列表,并在组(树的叶子)内使用跳转表

  • 所以答案是,是的,有时,但不是那么简单

    可以使用默认跳转填充“空”大小写槽,以允许构建密集范围。对于小分支,或针对非整数值的分支,将重写开关,就像重写条件一样(例如允许切换字符串或正则表达式的语言)。在您的示例中,数字0-9的大小写肯定会被编码为查找表,因为它是一个密集组

    在所有情况下,二叉决策树都是发出有效开关/案例结构的重要部分


    NET CLR甚至有一个接受跳转表的操作码,它隐藏了对默认情况的处理,这允许运行时在不进行全流分析的情况下验证代码是否安全。

    否;它们使用查找表。请记住,实现在很大程度上取决于编译器。有时使用一种技术,有时使用另一种。优化程度最高健壮的编译器是试图使用最佳方式的组合。@rici的可能重复:我认为问题不同,因为这只是编译器如何处理此类语句的问题,而不是语言如何处理它们的问题:在某些语言中,顺序在语义上可能很重要,但仍然有一个关于如何处理这些语句的讨论编译器有效地实现了一个切换用例,而且您链接到的问题也被关闭了:(@CommuSoft:所有提到的语言都有相同的语义,顺序在语义上并不重要;问题是编译器如何处理它。答案是,“这取决于”。这与您的问题的答案相同。此外,请参阅和,可能还有更多。如果使用查找表,这是否能够为支持哈希代码的所有类型的对象使用switch-case语句?不仅是文本?而且是类似于
    case-new-Person(“James”,25)的语句:
    那么这样的实例可以在编译时构造并存储在查找表中。理论上是的,编译器要高效地编译它,必须能够将哈希值压缩或映射到密集范围(我想使用模),所以你必须提供一个允许这种情况的哈希函数,加上编译器必须提供一个钩子。否则它就剩下了二进制决策树。@CommuSoft-你实际上给了我一些动力,让我在我的Cola编译器中尝试这种方法。我支持整数值、字符串和最终的正则表达式模式,但我喜欢tr的想法还有基于对象的切换。我想我会试一试。@CommuSoft-Scala和Haskell等语言中的通用模式匹配支持可以“切换”对象。我还没有看过实现,但可能值得一看,因为您对编译器感兴趣。