まず、問題はif
ではありません。あなたが見たとおり、gcc
はif
を見て、30
をそのままprintf
に渡します。
は今、gcc
は(特に、それがputs("something")
にprintf("something\n")
とさえprintf("%s\n", "something")
を最適化しています)printf
の特殊なケースを処理するためにいくつかのロジックを持っているが、それは非常に固有のものであり、更に多く行っておりません。例えば、printf("Hello %s\n", "world")
はそのまま残されます。さらに悪いことに、の変種のいずれかがの末尾にある場合は、そのままfputs("something", stdout)
に変換することができます。
私は、この2つの主要な問題に降りてくることを想像:
上記の2例は、実装するために非常に簡単パターンであり、かなり頻繁に起こるが、残りのため、おそらくそれはめったに努力の価値ません。文字列が一定でパフォーマンスが重要な場合は、プログラマが簡単に処理できます。実際には、printf
のパフォーマンスが重要な場合は、このような最適化に頼るべきではありません。文字列。
上記のputs
の最適化だけでもすでに「スタイルポイント」になっている場合でも、人為的なテストケース以外は、実際には深刻なパフォーマンスを得ることはありません。
%s\n
の領域外に出ると、printf
は実行時環境に強く依存するため、地雷です。特に、多くのprintf
指定子は(残念なことに)ロケールの影響を受けています。さらに、実装特有の癖や指定子があります(gcc
はglibc、musl、mingw/msvcrtのprintf
で動作します...コンパイル時には、ターゲットのCランタイムを呼び出すことはできません。クロスコンパイル時には思っています)。
私はこのシンプルな%d
のケースはおそらく安全だと同意しますが、なぜ過度にスマートにならないようにして、ここで最も愚かでも安全な最適化のみを行うことにしたのか分かります。好奇心読者の
、この最適化が実際に実施される場合hereです。ご覧のとおり、この機能は限られた数の非常に単純なケースと一致します(GIMPLEを除いて、this nice articleが書かれて以来、多く変更されていません)。ちなみに、ソースは実際に、なぜ改行以外の場合にfputs
バリアントを実装できなかったのかを説明しています(そのコンパイル段階でstdout
グローバルを参照する簡単な方法はありません)。
'gcc'は' printf'出力を予測できません。 – LPs
@LPs AFAIKでは、可能であればputs()とputchar()の呼び出しでprintf()の呼び出しを変更します。 – Mitsos101
@ Mitsos101は*既知のコンパイル時定数のみ*。あなたのコードであなたが見ていることは、それを実行することによってのみ決定できます。簡単にあなたの頭の中で行うことができます。 – adelphus