何が起きてる:
printf("result = %d\n", 1);
printf("result = %f\n", 1);
出力:
result = 1
result = 0.000000
これらの変数を印刷する前に型を確認すれば、もちろん問題なく動作します。2 番目の print ステートメントが暗黙的に 1.00000 に変換されないのはなぜですか?
何が起きてる:
printf("result = %d\n", 1);
printf("result = %f\n", 1);
出力:
result = 1
result = 0.000000
これらの変数を印刷する前に型を確認すれば、もちろん問題なく動作します。2 番目の print ステートメントが暗黙的に 1.00000 に変換されないのはなぜですか?
2 番目のケースでは、フォーマット文字列と引数の型が一致しません。したがって、結果は未定義の動作になります。
1 が 1.0 に変換されない理由はprintf
、可変数の引数を持つ「単なる」C 関数であり、最初の (必須の) 引数のみが指定された型 ( const char *
) を持つためです。したがって、コンパイラは「余分な」引数を変換する必要があることを「認識できません」。実際にフォーマット文字列を読み取る前 printf
に渡され、浮動小数点数を取得する必要があると判断します。
確かに、フォーマット文字列はコンパイル時の定数であるため、コンパイラは特別なケースを作成して、間違った引数について警告printf
する可能性があります(他の人が述べたように、一部のコンパイラは、少なくとも要求された場合にこれを行います) . しかし、一般的なケースでは、任意の vararg 関数で使用される特定の形式を知ることはできず、複雑な方法で (実行時などに) 形式文字列を構築することもできます。
結論として、特定の型を「変数」引数として渡したい場合は、キャストする必要があります。
未定義の動作。int が float として扱われている
簡単に言えば、printf は実際には C++ ではないということです。Printf は、可変引数リストを取り、指定された引数を書式文字列に指定された型に基づいて書式文字列に適用する C 関数です。
何らかの種類の実際の型チェックが必要な場合は、ストリームと文字列を使用する必要があります。これは、古き良き C スタイルの printf に代わる実際の C++ です。
興味深いことに、おそらく「1.0」を入力しても問題ありません
printf は変数のアドレスを取得するだけで、それが何であるかを知る方法がないと思います。しかし、私はコンパイラがあなたに警告する良識があると思っていたでしょう。