使用goto来逃避控制结构是否会产生不同的组装?

Does Using goto to Escape Control Structures Ever Produce Different Assembly?

本文关键字:goto 逃避 控制结构 是否 使用      更新时间:2023-10-16

关于goto命令有很多争论,这个问题不是关于使用它的正确或错误,而更简单的问题是它是否实际上创建了不同的汇编。

我特别关注Visual Studio 2013,但任何编译器的示例都很棒。

Bjarne Stroustrup状态:

标签的作用域是它所在的函数(§6.3.4)。这意味着您可以使用goto跳到块中或跳出块。唯一的限制是不能跳过初始化式或异常处理程序(§13.5)。goto在普通代码中为数不多的合理用途之一是跳出嵌套循环或switch -语句。

那么,我的问题是:是否存在goto仍然产生不同于使用其他控制结构已经可以完成的组装的实例?

例如,这会产生相同的程序集:

auto r = rand();
auto a = 0;
for(auto i = rand(); i > 0; --i){
    switch(r){
    case 1:
        ++sum;
        goto END;
    case default:
        sum += rand();
        break;
    }
}
sum++;
END:

对于这个非goto代码:

auto r = rand();
auto b = false;
auto a = 0;
for(auto i = rand(); i > 0; --i){
    switch(r){
    case 1:
        ++sum;
        b = true;
        break;
    case default:
        sum += rand();
        break;
    }
    if(b)break;
}
if(!b)sum++;

这是我的经验:我曾经有一段代码非常时间紧迫。它有一个平均迭代0次的循环(while (condition)…),条件几乎总是假的。编译器坚持循环优化,把东西移到循环之外——即使循环根本没有执行,因此减慢了它的速度。

我尝试使用goto重写循环,希望混淆优化器以放弃优化代码,但失败了。gcc和clang的优化取决于实际的控制流,而不是取决于您使用的C或c++代码。