printf
関数のプロトタイプは
int printf(const char * restrict format, ...);
最初の引数は常に、出力の形式を説明するテキスト文字列です(したがって、単にprintf(fruit);
. は、フォーマット文字列の後に 0 個以上の追加の引数を取る可能性があることを...
示します (これは可変引数関数として知られています)。 printf
残念ながら、可変個引数関数は、引数リストの変数部分で渡される引数の数または型を自動的に認識しません。最後の固定引数の後に、次に使用可能な引数の開始アドレスが表示されるだけです。どうにかしてその情報を固定引数の一部として渡す必要があります。ではprintf
、追加の引数の数と型は、書式文字列の変換指定子によって示されます。だからあなたが書くとき
printf("%f\n", fruit);
変換指定子%f
は、書式文字列の後printf
に型の追加の引数が 1 つあることを示しています。double
変換指定子はprintf
、表示用に値をフォーマットする方法も指定します。たとえば、
printf("%7.2f\n", fruit);
変換指定子は、小数点以下 2 桁の 7 文字幅のフィールドとして値を表示する%7.2f
よう指示します。または. printf
9999.99
引数の型が変換指定子と一致しない場合、動作は未定義です。たとえば、次のように書くと
printf("%d\n", fruit);
実際には を渡すときにprintf
を期待するように指示していますが、これは論理エラーです。基盤となるアーキテクチャによっては、さまざまなことが発生する可能性があるため、動作は未定義のままであり、コンパイラはそれについて特に何もする必要はありません。どの結果も「正しい」と見なされます。本当に優れたコンパイラは、引数が変換指定子と一致しないという診断を発行します。ほとんどの場合、コードをそのまま変換するだけで、予期しない出力からアクセス違反まで、さまざまな結果が生じる可能性があります。 int
double
同様に、変換指定子の数に一致する十分な引数を渡さない場合、動作は未定義です。
printf("%f %d\n", fruit);
変換指定子よりも多くの引数を渡すと、追加の引数が評価されますが、それ以外の場合は無視されます。
printf("%f\n", fruit, apples, bananas);