【问题标题】:implicit else compiler optimization隐式 else 编译器优化
【发布时间】:2017-03-01 12:20:38
【问题描述】:

我想知道编译器是否有办法理解两个 if 语句不能同时为真,并添加“隐式 else”。例如在此代码示例中:

int main() {
    char c;
    scanf_s("%c", &c, 1);
    if (c == '1') {
        printf("received 1\n");
    }

    if (c == '2') {
        printf("received 2\n");
    }

    return 0;
}

c 不能是'1' 和 '2',但是在Visual Studio 中编译和反汇编后,我注意到它会检查第二个if,无论如何。

【问题讨论】:

  • 检查发布版本。
  • 除了“有可能,但取决于编译器”,您还期待什么答案?
  • 除非有人非常具体地教编译器 scanf 和 printf 做什么,否则 scanf 可能会将指向 c 的指针存储在某个全局变量中,而 printf 可能会通过该指针修改 c。如果你用不那么不透明的东西替换 printf,gcc 会进行优化。
  • @Toby - 在这方面你比我更乐观。我认为“C/C++”问题的倾盆大雨永远不会减少。
  • 磁盘空间不足吗?为什么不使用} else if ...?在你写完这个问题的时候,你可以看看生成的汇编代码,或者——更好的是——添加else。

标签: c compiler-optimization


【解决方案1】:

我想知道编译器是否有办法理解两个 if 语句不能同时为真,并添加“隐式 else”。

是的,有:Intel C 编译器icc 17 可以,正如Matt Godbolt's Compiler Explorer 所验证的那样,但clang 和gcc 似乎都没有执行此优化。

【讨论】:

    【解决方案2】:

    我将在 LLVM/CLANG 的上下文中回答,因为我不太熟悉它的内部结构。

    如果您确实在 opt 中打开了 mem2reg 优化,它将把 c 视为临时变量而不是堆栈上的变量(在寄存器分配之前的阶段)。

    优化器可以做出所需的假设,在这种情况下,假设第二个如果在第一个内部,它将被 DCE 删除。

    但我想不出 LLVM 套件中的任何传递都会添加“elseif”。

    对于 gcc/msvc 等其他编译器则不能这样说。

    【讨论】:

      【解决方案3】:

      编译器可以理论上执行您建议的优化吗?是的,它绝对可以,但确保在编译器中检测此类安全场景所需的语义分析没有错误绝对不是微不足道的,问题是是否不能花费开发工作其他地方更好。

      【讨论】:

        【解决方案4】:

        因为scanf_s() 被赋予了一个指向变量c 的指针,所以这个变量不能再被视为一个局部变量。先验地,该函数可以将此指针存储在某处,并且任何其他函数(编译器未知)可以通过此指针存储某些内容,例如对 printf("received 1\n") 的调用。

        换句话说,除非编译器知道函数 scanf_s() 和 printf() 正在做什么,否则编译器无法进行此优化。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-15
          • 1970-01-01
          • 2011-11-07
          • 2014-02-21
          • 2011-08-24
          • 2012-02-12
          相关资源
          最近更新 更多