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){
}
答案 0 :(得分:5)
C标准说(C11 5.1.2.3/4):
在抽象机器中,所有表达式都按照指定的方式进行评估 语义学。实际的实现不需要评估部分内容 表达式,如果它可以推断出它的值没有被使用而且没有 产生所需的副作用(包括通过调用a引起的任何副作用) 功能或访问易失性对象。)
因此编译器可以自由地优化函数调用,除非函数包含任何“需要的”副作用。措辞有点模糊,可能以不同的方式解释。但实际上,所有编译器都很可能优化掉空函数。
答案 1 :(得分:4)
当他查看已编译的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;
}