2

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

4 回答 4

7

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

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

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

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

于 2013-10-22T06:21:03.210 回答
6

C标准说(C11 5.1.2.3/4):

在抽象机中,所有表达式都按照语义的规定进行评估。如果一个实际的实现可以推断出它的值没有被使用并且没有产生所需的副作用(包括调用函数或访问易失性对象引起的任何副作用),则它不需要评估表达式的一部分。

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

于 2013-10-22T06:22:31.210 回答
2

是的,如果被告知要优化编译器,也可能会优化掉什么都不做的代码。

然而,大多数编译器默认不进行优化。

对于 gcc,有 1 + 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) 进行的快速测试表明,已经-O1在 OP 的示例代码上使用会导致 OP 的假设。


有趣的是,即使是显式return 0的也被优化了-O1

于 2013-10-22T06:15:37.770 回答
0

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

int main(int argc, char**argv) {
   printf("abcde")
   return 0;
}
于 2013-10-22T06:19:36.677 回答