当打印静态的、没有格式的字符串时,C 编译器通常会执行一些优化,将类似于 printf("foobar\n");
的调用转换为等效的 puts("foobar");
。只要不使用返回值就可以这样做(C 指定printf
在成功时返回写入的字符数,但是puts
仅在成功时返回非负值)。C 编译器还会将类似于 fprintf(stdout, "foobar")
的调用转换为 fwrite("foobar", 1, 6, stdout)
。
然而,printf
到 puts
的优化仅适用于字符串以换行符结尾的情况,因为 puts
会自动添加一个换行符。如果没有换行符,我期望 printf
可以被优化为等效的 fwrite
,就像 fprintf
那样——但是似乎编译器并不这样做。例如,下面的代码(Godbolt链接):
#include <stdio.h>
int main() {
printf("test1\n");
printf("test2");
fprintf(stdout, "test3");
}
在汇编语言中,gets被优化为以下调用序列:
puts("test1");
printf("test2");
fwrite("test3", 1, 5, stdout);
我的问题是:在没有终止换行符的情况下,为什么编译器不会将
printf
优化为fwrite
或类似函数?这只是一种被忽视的优化,还是printf
和fwrite
在使用静态、无格式字符串时存在语义差异?如果相关,请提供适用于C11或任何更新标准的答案。
fprintf(stdout, "test3");
和fwrite("test3", 1, 5, stdout);
相比于printf("test3");
没有什么理由,除了前者使用了stdout
。 - chux - Reinstate Monicafputs()
优化。但在从gcc 7到11的测试后,没有进行这样的优化。printf
->puts
等的汇编优化似乎是基础编译器选择,不受-Ox优化级别选择的影响。 - David C. Rankinwrite
可以,但标准C的fwrite
不行。 - Nate Eldredge