【问题标题】:if statement, function evaluation & compiler optimizationif 语句、函数评估和编译器优化
【发布时间】:2020-07-10 13:08:56
【问题描述】:

只是一个简单的问题,以免我测试事物(尽管我真的应该测试事物以绝对确定):

给定以下 C 代码:

r1 = fun1();
r2 = fun2();

if (r1 && r2)
{
   // do something
}

变量r1r2 没有在代码中的任何其他地方使用,if (...) 语句除外。是否会评估这两个功能?我担心编译器可能会通过消除r1r2来优化代码,从而使它看起来像这样:

if (fun1() && fun2())
{
   // do something
}

在这种情况下,fun1() 将首先被评估,如果它返回 FALSE,那么 fun2()被评估。这不是我想要的,这就是我将它编码为第一个代码段的原因。

我如何保证函数将总是被评估?我认为这可以通过将它分配给一个变量来完成,但是如果它发现这个变量以后实际上从未在代码中使用过,我会担心编译器优化......

我知道这可以通过将 r1r2 声明为 volatile 来实现,但我想知道是否有更优雅的解决方案。

非常感谢有关此问题的任何 cmet,谢谢!


编辑:感谢所有回复的人。我刚刚在我的项目中使用了我的第一个代码 sn-p(它是一个基于 ARM Cortex-M7 的嵌入式系统)。看来编译器确实没有按照我上面显示的方式优化代码,并且 fun1()fun2() 都被评估(应该如此)。此外,使用声明为volatiler1r2 编译代码会产生与r1r2 只是普通变量时完全相同的二进制输出(即volatile 关键字不会改变编译器输出)。这让我放心,第一个代码 sn-p 实际上是在处理随后的 if (...) 语句之前评估 两个 函数的保证方法。

【问题讨论】:

  • 你可能需要看看反汇编。
  • 它不会优化调用,除非它可以评估结果编译时间
  • @FiddlingBits 这不会告诉您任何可靠的信息,因为即使使用相同的编译器,确切的程序集也会立即更改。获得可靠信息的唯一方法是遵循此处的规范。

标签: c if-statement compiler-optimization volatile evaluation


【解决方案1】:

假设代码没有表现出任何未定义的行为,编译器只能执行与未优化代码具有相同外部可见行为的优化。

在您的示例中,两段代码做了两件不同的事情。具体来说,一个总是调用fun2,而另一个有条件地调用它。所以你不必担心第一段代码会做错事。

【讨论】:

    【解决方案2】:

    除非调用的结果可以计算编译时间,否则不会优化调用。

    void foo()
    {
        int r1 = fun1();
        int r2 = fun2();
    
        if (r1 && r2)
        {
            func3();
        }
    }
    
    int fun3() {return 1;}
    int fun4() {func();return 0;}
    
    void bar()
    {
        int r1 = fun3();
        int r2 = fun4();
    
        if (r1 && r2)
        {
            func3();
        }
    }
    
    foo:
            push    {r4, lr}
            bl      fun1
            mov     r4, r0
            bl      fun2
            cmp     r4, #0
            cmpne   r0, #0
            popeq   {r4, pc}
            pop     {r4, lr}
            b       func3
    fun3:
            mov     r0, #1
            bx      lr
    fun4:
            push    {r4, lr}
            bl      func
            mov     r0, #0
            pop     {r4, pc}
    bar:
            b       func
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-18
      • 1970-01-01
      • 2015-09-12
      • 1970-01-01
      • 2013-05-17
      • 2010-12-27
      • 1970-01-01
      • 2010-11-20
      相关资源
      最近更新 更多