鉴于以下内容:
len = strlen(str);
/* code that does not read from len */
len = new_len;
我可以依赖编译器删除第一行吗?
我正在编写代码生成脚本。第一行是在一个地方生成的,而后面的所有内容都是在其他地方生成的(通过后代类中的虚函数)。大多数时候,不需要len。有时虽然如此。我想知道我是否可以在所有情况下都设置它,如果不需要,让编译器摆脱它。
答案 0 :(得分:4)
不,当然你不能“依赖”编译器完成的优化选择。
它们可以根据用户的奇思妙想(编译器命令行选项)或使用不同的编译器版本进行更改。
由于语言标准不要求您描述的行为,因此您不能依赖编译器来实现它。
另一方面,你可以测试它,并尝试“哄”它进行优化,例如(再次)要求你的编译器做尽可能多的优化,例如。
答案 1 :(得分:2)
编译器非常聪明。但依靠编译器删除"未使用"函数调用可能不是一个好主意。首先,编译器需要理解你正在调用的函数(因此strlen是一个很好的例子,因为大多数编译器都了解strlen的作用以及它如何影响其他事物) - 如果函数不是编译器的那个&# 34;理解"然后它无法优化它。
如果您这样做了:
x = printf("Hello, World!\n");
x = printf("World, Hello!\n");
您是否认为他们的编译器通过删除第一个printf做了正确的事情?可能不是......所以,使用任何函数,编译器都无法确定"是无副作用的",编译器必须调用该函数,即使结果未被使用。无副作用意味着在正常情况下 - 例如使用无效指针调用strlen()会产生副作用 - 您的代码可能会崩溃 - 但这不是"正常情况" - 使用strlen()只是为了检查你的指针是否有效,对吗?
因此,换句话说,您可能希望确保在调用strlen之前确实需要调用strlen() - 或者考虑到编译器可能会生成不必要的strlen调用。
答案 2 :(得分:1)
现代编译器似乎在消除冗余分配方面做得非常出色。我通过VS 2008和gcc 4.6运行了以下片段,并且实际上删除了对strlen(内联代码)的调用。两个编译器都设法看到something()
和something_else()
都没有副作用。对这些的调用也会被删除。
这发生在VC中的/ O1和gcc中的/ O1中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int something(int len) {
if(len != len) {
printf("%d\n", len);
}
return 0;
}
int something_else(int len) {
return len * len;
}
int main(void) {
char *s = malloc(1000);
size_t len;
strcpy(s, "Hello world");
len = strlen(s);
something(len);
printf("%s\n", s);
len += 8;
something_else(len);
len = 5;
printf("%d\n", len);
return 0;
}
答案 3 :(得分:0)
这取决于编译器和&amp;您指定的优化级别。
这里最初从函数调用中分配。如果该功能有副作用怎么办?
所以你不能只假设编译器为你优化它。
如果初始转让声明没有任何副作用,你指定优化级别足够好(例如gcc的情况下为-O3),它可以为你优化它。