这是我的测试代码:
#include<stdio.h>
static inline void foo(int a){
printf("%x\n", a);
}
int main(void){
foo(0x1234);
return 0;
}
我认为 GCC 应该意识到 a
是一个文字整数,并优化为这样的代码:
puts("1234");
但是我得到了如下的汇编代码:
│0x8048341 <main+17> push $0x1234
│0x8048346 <main+22> push $0x80484e0
│0x804834b <main+27> push $0x1
│0x804834d <main+29> call 0x8048310 <__printf_chk@plt>
在我的项目中有很多这样的代码,因为我一直相信GCC会为我优化,甚至在一些可以简单地使用'write()'的上下文中,我坚持使用printf
,因为我认为我会从它的缓冲机制中获益。
现在我感到很遗憾,因为削减格式字符串的开销会扼杀我的任何收获。我项目中的这些代码非常底层,它们可能会导致性能瓶颈。
最佳答案
These codes in my project are quite low-level, and they might cause the performance bottleneck.
首先,我可以消除您对这不可能的恐惧。控制台 I/O 的开销是巨大的(相对而言),因此无论您使用什么方式,这始终是您代码中的瓶颈。
I thought gcc should realize that
a
is a literal integer, and optimize to code like this:puts("1234");
显然不是。 GCC(和 Clang)does perform an optimization where printf("...\n");
is transformed into puts("...");
,如您所见here ,但这只会在您将 string literals 与 printf
一起使用时发生。优化器(当前)不会查看格式字符串、解析它并围绕它进行优化。你调用了 printf
,所以你得到了 printf
。
编译器优化不是保证,因此您不应该编写依赖的代码,而不首先验证所需的优化实际上在所有情况下都得到应用您感兴趣的内容(包括代码变体、编译器版本、目标平台等)。
如果您想建议这是对 GCC 优化器的可能改进,您可以在 their Bugzilla 上提出增强建议.但是不要对它很快就会实现抱有希望。考虑到现实世界中预期的性能改进充其量是最小的(见上文),实现此类优化所需的逻辑并不值得付出努力。
与此同时,如果您绝对需要对代码进行最少更改的这种优化,那么您可以使用 some macro hackery :
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
#define foo(a) puts(STRINGIFY(a))
这确实会产生所需的输出:
.LC0:
.string "0x1234"
MyFunction:
sub esp, 24
push OFFSET FLAT:.LC0
call puts
xor eax, eax
add esp, 28
ret
关于c - 为什么 GCC 没有将这个 'printf' 优化为 'puts' ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44406798/