誰も言及していないので、彼らのパフォーマンスに関するメモを追加します。
通常の状況では、コンパイラーの最適化が使用されていない(つまり、printf()
実際にはが呼び出されprintf()
、呼び出されていないfputs()
)と想定するprintf()
と、特に長い文字列の場合、パフォーマンスが低下することが予想されます。これはprintf()
、変換指定子があるかどうかを確認するために文字列を解析する必要があるためです。
これを確認するために、いくつかのテストを実行しました。テストはgcc 4.8.4を使用してUbuntu 14.04で実行されます。私のマシンはIntel i5 cpuを使用しています。テスト中のプログラムは次のとおりです。
#include <stdio.h>
int main() {
int count = 10000000;
while(count--) {
// either
printf("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM");
// or
fputs("qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM", stdout);
}
fflush(stdout);
return 0;
}
どちらもでコンパイルされていgcc -Wall -O0
ます。時間はを使用して測定されtime ./a.out > /dev/null
ます。以下は典型的な実行の結果です(私は5回実行しましたが、すべての結果は0.002秒以内です)。
以下のためのprintf()
変種:
real 0m0.416s
user 0m0.384s
sys 0m0.033s
以下のためのfputs()
変種:
real 0m0.297s
user 0m0.265s
sys 0m0.032s
ストリングが非常に長い場合、この効果は増幅されます。
#include <stdio.h>
#define STR "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
#define STR2 STR STR
#define STR4 STR2 STR2
#define STR8 STR4 STR4
#define STR16 STR8 STR8
#define STR32 STR16 STR16
#define STR64 STR32 STR32
#define STR128 STR64 STR64
#define STR256 STR128 STR128
#define STR512 STR256 STR256
#define STR1024 STR512 STR512
int main() {
int count = 10000000;
while(count--) {
// either
printf(STR1024);
// or
fputs(STR1024, stdout);
}
fflush(stdout);
return 0;
}
printf()
バリアント(3回、本当のプラス/マイナス1.5秒を走りました):
real 0m39.259s
user 0m34.445s
sys 0m4.839s
fputs()
バリアント(3回、本当のプラス/マイナス0.2秒を走りました):
real 0m12.726s
user 0m8.152s
sys 0m4.581s
注: gccによって生成されたアセンブリを調べたところ、gccはを使用してもfputs()
、fwrite()
呼び出しの呼び出しを最適化していることに気付きました-O0
。(printf()
呼び出しは変更されません。)コンパイラーがfwrite()
コンパイル時にの文字列長を計算するため、これがテストを無効にするかどうかはわかりません。
printf("Hello World!")
はありませんputs("Hello World!")
。puts()
を追加し'\n'
ます。代わりprintf("abc")
にfputs("abc", stdout)