Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.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
C++ 在交换机中嵌套goto循环_C++_C - Fatal编程技术网

C++ 在交换机中嵌套goto循环

C++ 在交换机中嵌套goto循环,c++,c,C++,C,我想在一个序列上循环,但我想动态地选择在序列中开始循环的位置。我设计了这种流动模式 switch(offset){ start: currentObject = objects[index++]; //a different object is chosen to be manipulated by the sequence of code case 0: sub_sequence(currentObject); // a sequence that is

我想在一个序列上循环,但我想动态地选择在序列中开始循环的位置。我设计了这种流动模式

switch(offset){
    start:
    currentObject = objects[index++]; //a different object is chosen to be manipulated by the sequence of code
    case 0:
        sub_sequence(currentObject); // a sequence that is repeated within the larger sequence of the entire switch
        if(enough_actions) break;
    case 1:
        sub_sequence(currentObject);
        if(enough_actions) break;
    case 2:
        sub_sequence(currentObject);
        if(enough_actions) break;
    goto start;
    }
它似乎很适合我的需要,但我以前从未见过这种设计。这个设计有什么问题吗?我应该选择另一种方式吗?

您也可以:

switch(offset)
{
    do
    {
        currentObject = objects[index++]; //a different object is chosen to be manipulated by the sequence of code
        case 0:
            sub_sequence(); // a sequence that is repeated within the larger sequence of the entire switch
            if(enough_actions) break;
        case 1:
            sub_sequence();
            if(enough_actions) break;
        case 2:
            sub_sequence();
            if(enough_actions) break;
    }
    while (1);
}
所以你避开了goto;) (如评论中所述,如果需要这种行为,从技术上讲,避免
goto
是没有意义的)

但是,你是对的,两者都应该适合你的需要。

你也可以这样做:

switch(offset)
{
    do
    {
        currentObject = objects[index++]; //a different object is chosen to be manipulated by the sequence of code
        case 0:
            sub_sequence(); // a sequence that is repeated within the larger sequence of the entire switch
            if(enough_actions) break;
        case 1:
            sub_sequence();
            if(enough_actions) break;
        case 2:
            sub_sequence();
            if(enough_actions) break;
    }
    while (1);
}
所以你避开了goto;) (如评论中所述,如果需要这种行为,从技术上讲,避免
goto
是没有意义的)


但是,你是对的,两者都应该符合你的需要。

你在那里构建的是一个达夫装置。虽然它避免了重复的源代码,但它不仅很难为人类理解,而且也很难为编译器进行优化

switch(offset)
{
    case 0:
        sub_sequence(currentObject); // a sequence that is repeated within the larger sequence of the entire switch
        if(enough_actions) break;
    case 1:
        sub_sequence(currentObject);
        if(enough_actions) break;
    case 2:
        sub_sequence(currentObject);
        if(enough_actions) break;

        //a different object is chosen to be manipulated by the sequence of code
        currentObject = objects[index++];
        while(true) {
            sub_sequence(currentObject);
            if(enough_actions) break;
            sub_sequence(currentObject);
            if(enough_actions) break;
            sub_sequence(currentObject);
            if(enough_actions) break;
            currentObject = objects[index++];
        }
}
通过将循环与变量入口点分离,编译器可以更自由地执行优化

在原始代码中,它由
开始:
标签和3个
大小写:
标签分开,这迫使编译器分别处理两个标签之间的每个代码段

如果没有这些标签,编译器现在可以将特定于switch语句的优化应用于
switch
块,还可能对
while
循环应用额外的循环展开或其他策略

最后,使用可读性更强的变体可能会产生更紧凑和更快的机器代码

这可以说是少数几个可以接受“复制”代码的情况之一,因为
开关
while
块看起来很相似,但行为仍然完全不同

EDIT1:将循环移动到switch语句的末尾,以便正确处理
足够多的动作。如果不存在提前退出的条件,则循环可能被置于
开关
块之外

奖励:无交换机实施:

for(;!enough_actions;offset = 0,currentObject = objects[index++]) {
    for(int i = offset; i < 3 && !enough_actions; i++) {
        sub_sequence(currentObject);
    }
}
(;!足够多的动作;偏移量=0,当前对象=objects[index++])的
{
对于(int i=offset;i<3&!足够多的动作;i++){
子序列(currentObject);
}
}

您在那里构建的是一个达夫装置。虽然它避免了重复的源代码,但它不仅很难为人类理解,而且也很难为编译器进行优化

switch(offset)
{
    case 0:
        sub_sequence(currentObject); // a sequence that is repeated within the larger sequence of the entire switch
        if(enough_actions) break;
    case 1:
        sub_sequence(currentObject);
        if(enough_actions) break;
    case 2:
        sub_sequence(currentObject);
        if(enough_actions) break;

        //a different object is chosen to be manipulated by the sequence of code
        currentObject = objects[index++];
        while(true) {
            sub_sequence(currentObject);
            if(enough_actions) break;
            sub_sequence(currentObject);
            if(enough_actions) break;
            sub_sequence(currentObject);
            if(enough_actions) break;
            currentObject = objects[index++];
        }
}
通过将循环与变量入口点分离,编译器可以更自由地执行优化

在原始代码中,它由
开始:
标签和3个
大小写:
标签分开,这迫使编译器分别处理两个标签之间的每个代码段

如果没有这些标签,编译器现在可以将特定于switch语句的优化应用于
switch
块,还可能对
while
循环应用额外的循环展开或其他策略

最后,使用可读性更强的变体可能会产生更紧凑和更快的机器代码

这可以说是少数几个可以接受“复制”代码的情况之一,因为
开关
while
块看起来很相似,但行为仍然完全不同

EDIT1:将循环移动到switch语句的末尾,以便正确处理
足够多的动作。如果不存在提前退出的条件,则循环可能被置于
开关
块之外

奖励:无交换机实施:

for(;!enough_actions;offset = 0,currentObject = objects[index++]) {
    for(int i = offset; i < 3 && !enough_actions; i++) {
        sub_sequence(currentObject);
    }
}
(;!足够多的动作;偏移量=0,当前对象=objects[index++])的
{
对于(int i=offset;i<3&!足够多的动作;i++){
子序列(currentObject);
}
}

我已经检查了Microsoft编译器为以下斐波那契函数生成的汇编代码,编译器仍然能够稍微修改未展开的循环序列(我假设可以优化寄存器依赖项)

也许这更适用于线性反馈移位寄存器等情况,其中循环被展开以保存变量之间的移位数据。例如:

    while(...){
        e = f(a,b,c,d);
        a = b;
        b = c;
        c = d;
        d = e;
    }
展开成

    do{
        a = f(a,b,c,d);
      case 3:
        b = f(b,c,d,a);
      case 2:
        c = f(c,d,a,b);
      case 1:
        d = f(d,a,b,c);
      case 0:
    }while(...);

如果元素的数量不是4的倍数,那么使用达夫的设备进入展开的循环

我已经检查了Microsoft编译器为下面的斐波那契函数生成的汇编代码,编译器仍然能够稍微修改展开的循环序列(我假设可以优化寄存器依赖项)

也许这更适用于线性反馈移位寄存器等情况,其中循环被展开以保存变量之间的移位数据。例如:

    while(...){
        e = f(a,b,c,d);
        a = b;
        b = c;
        c = d;
        d = e;
    }
展开成

    do{
        a = f(a,b,c,d);
      case 3:
        b = f(b,c,d,a);
      case 2:
        c = f(c,d,a,b);
      case 1:
        d = f(d,a,b,c);
      case 0:
    }while(...);

如果元素的数量不是4的倍数,那么使用达夫的设备进入展开的循环

为什么不绕着开关转一圈呢?您可以避免跳转。您只需将其插入
while
循环中即可。@RichardHodges如果您在linux内核中看到Duff的设备,请立即提交修补程序。将循环从switch语句中切掉,从而“展开”Duff的设备,可以提高可读性,并使编译器能够执行适当的优化,否则这些优化会被这些讨厌的标签阻止。(无论是显式的
start:
标签还是
switch
语句中的
case
标签。)@Ragdoll每当遇到标签时,编译器都必须将代码分成不同的部分。它不再能够在这些部分之间交换或合并指令,或者应用任何其他会改变后一部分行为的优化。在这种情况下,常规循环优化和