当前位置: 首页 > 知识库问答 >
问题:

为什么检查没有被优化

谭兴学
2023-03-14

今天我开始玩分支,检查两个布尔值。我很确定,在某些优化级别上,它们将简单地添加并检查,但gcc和CLANG不是这样。为什么gcc不优化两个bool检查,用addition和一个check替换它们?让我给你看一个例子:

void test(bool a, bool b)
{ 
    // Branch 1
    if (a && b)
    {
        std::cout << "Branch 1";
    }

    // Branch 2
    if (static_cast<int>(a) + static_cast<int>(b))
    {
        std::cout << "Branch 2";
    }
}
test   dil,dil
je     400794 <test(bool, bool)+0x14>
test   sil,sil
jne    4007b0 <test(bool, bool)+0x30>
movzx  ebx,bl
movzx  ebp,bpl
add    ebx,ebp
jne    4007cf <test(bool, bool)+0x4f>

两个分支(test+je)不应该比加法和分支(add+jne)慢吗?

编辑:我真正的意思是乘法,因为在true和false的情况下(1+0),加法给出true(1),但乘法给出正确的结果(0)。

共有1个答案

狄卓君
2023-03-14

在抽象机器级别,&&强制不计算第二个表达式,如果第一个表达式为false。根据as-if规则,编译器无论如何都可以选择计算第二个表达式--如果它能够证明它已经定义了行为(或者未定义的行为无关紧要)并且没有副作用;然而,编译器编写者显然认为这是不值得的。

如果您不想简单化,&可能会有帮助(带有注释)。

 类似资料:
  • 问题内容: 我写了一个简单的基准测试,以找出在通过按位和计算数组时是否可以消除边界检查。基本上,这就是几乎所有哈希表的作用:它们计算 作为一个指数到的,其中是或派生值。该结果表明,范围检查没有得到消除。 我的基准测试的想法很简单:计算两个值和,保证两个值都是有效的数组索引。 是循环计数器。当它用作数组索引时,将取消边界检查。 将计算为,其中每次迭代中都有一些值更改。当它用作数组索引时,不会消除边界

  • 因此,我的问题是:为什么还没有被否决?如果核心Java团队已经决定它是坏的,那么他们一定也考虑过弃用。他们反对这样做的理由是什么(在Java8中,它仍然没有被反对)?

  • 我正在学习Java,正在使用java 8,spring 5.3.9和Apache Tomcat 9。我已经将我的jar文件添加到我的构建路径中的类路径中,将Apache Tomcat添加到我的服务器中,我的项目运行得非常好。现在我开始使用beans和xml文件,我遇到了一个问题。我的代码的一部分被触发,另一部分被忽略。 我有以下界面 FortuneService.java: 和一个快乐财富服务类:

  • 在Java API中,它声明公共StringBuilder类扩展Object,但实际上,OpenJDK声明它扩展包私有AbstractStringBuilder类。问题:为什么Java API不能声明它扩展了AbstractStringBuilder? OpenJDK-公共最终类StringBuffer扩展AbstractStringBuilder实现java.io.Serializable,Ch

  • 问题内容: 此问题与旧Java版本的行为以及双重检查锁定算法的旧实现有关 较新的实现使用volatile并依赖于略有更改的语义,因此它们 不会 损坏。 声明字段分配始终是原子的,除了long或double字段。 但是,当我阅读解释为什么双重检查锁定被破坏时,据说问题出在赋值操作中: 线程A注意到该值未初始化,因此它获得了锁并开始初始化该值。 由于某些编程语言的语义,允许编译器生成的代码在A完成执行

  • 问题内容: 我正在尝试做这样的事情: 不幸的是,即使在Java 9中也不存在。 为什么它被遗漏了? 建议的解决方法是什么? 问题答案: 为什么它被遗漏了? 该API提供了可重用的构建块。这里的相关积木是,,。通过这些,您可以实现所需的功能:将流内映射到对象,然后获得平面图。提供构建基块的排列是不切实际的,并且很难扩展。 建议的解决方法是什么? 如前所述,使用可用的构建基块(+ ):