C编译器是否允许优化冗余语句?

时间:2013-10-22 06:13:21

标签: c compiler-optimization

C中有很多语句什么都不做。这意味着删除它们将在程序行为中没有可观察到的变化。

根据C标准,是否允许C编译器优化掉这些冗余语句?

例如,如果我们有这样的代码:

#include <stdio.h>

void f(void);

int main(void){

    printf("a");
    f(); // function call statement that provably does nothing

    printf("b");
    1000; // redundant expression statement

    printf("c");
    ; // null statement

    printf("d");
    int x = 1; // assignment statement that is not used

    printf("e");

    return 0;
}

void f(void){
    1000; // redundant expression statement
    ; // null statement
    int x = 1; // assignment statement that is not used
}

是否允许编译器生成与下面相同的目标代码? :

#include <stdio.h>

void f(void);

int main(void){
    printf("a");
    printf("b");
    printf("c");
    printf("d");
    printf("e");
    return 0;
}

void f(void){
}

4 个答案:

答案 0 :(得分:5)

C标准说(C11 5.1.2.3/4):

  

在抽象机器中,所有表达式都按照指定的方式进行评估   语义学。实际的实现不需要评估部分内容   表达式,如果它可以推断出它的值没有被使用而且没有   产生所需的副作用(包括通过调用a引起的任何副作用)   功能或访问易失性对象。)

因此编译器可以自由地优化函数调用,除非函数包含任何“需要的”副作用。措辞有点模糊,可能以不同的方式解释。但实际上,所有编译器都很可能优化掉空函数。

答案 1 :(得分:4)

回到80年代,我的一个朋友告诉我,他写了一个程序,执行一个计算pi的算法,然后打印出来。

当他查看已编译的exe文件时,他惊讶地看到编译器基本上产生了:输出3.14159

简而言之,C(或任何其他语言)编译器可以做任何事情以及所有不会改变程序行为的事情。

这也适用于Java等,其中JVM采用多种技术来提高速度(例如“解包”循环,因此代码按顺序执行而不经历循环开销等)

答案 2 :(得分:1)

是的,如果被告知要优化编译器,也可能会放弃无效的代码。

但是大多数编译器默认情况下不会优化。

对于gcc,有一个+3个级别:

-Ox with  x = {0, 1, 2, 3} (0 does not optimise and is the default)

使用gcc进行快速测试((Debian 4.4.5-8)4.4.5)表明已经在OP的示例代码中使用-O1会产生OP所假设的内容。


有趣的是,即使明确的return 0也会在-O1之后进行优化。

答案 3 :(得分:0)

它在很大程度上取决于编译器删除的内容,以及它的长度。有些编译器甚至可能在某些设置中删除整个静态函数(不仅仅是它们的调用,甚至是它们的定义),而其他编译器可能非常保守,并且不会删除任何内容。换句话说,它可能几乎是所述的目标代码,或者甚至可能是

int main(int argc, char**argv) {
   printf("abcde")
   return 0;
}