printf()が「%f」だけで問題ないのに、scanf()がdoubleに「%lf」を必要とするのはなぜですか?


179

引数がaであるかa であるかに関わらず、「を読むとき、いつ使用できるのか」に「」scanf()が必要なのはなぜですか。l%lfdoubleprintf()%fdoublefloat

コード例:

double d;
scanf("%lf", &d);
printf("%f", d);

1
POINTERの意味がわかりません。scanfで渡すのは&variable(ie)addressだけなので、ポインタはどこ

7
@deetchanya Cでは、単項演算&子で変数の「アドレスを取得」すると、その演算の結果は、メモリ内の変数の格納場所へのポインターになります。に渡されるのはそのポインタscanfです。
zwol 2013年

回答:


207

なぜなら、Cは可変引数を取る関数に対して浮動小数点を倍精度に昇格させるからです。ポインタは何に昇格されていないので、あなたが使用する必要がある%lf%lgまたは%le(または%laダブルスで読み取ることがC99で)。


26

С99以降、Cの書式指定子と浮動小数点引数の型の一致はprintf、との間で一貫していscanfます。です

  • %f ために float
  • %lf ために double
  • %Lf ために long double

typeのfloat引数が可変個引数として渡されると、そのような引数は暗黙的にtypeに変換されdoubleます。これが、printf書式指定子%f%lfが同等で交換可能な理由です。ではprintf、あなたは、「利用を横断する」ことが可能%lffloat%fdouble

しかし、実際にそれを行う理由はありません。使用しないでください%fprintf型の引数double。それはC89 / 90回に生まれた広範囲の習慣ですが、それは悪い習慣です。for を使用%lfprintf、引数用に予約してください。double%ffloat


1
コンパイラーにC99準拠のライブラリがない場合は%f、使用%lfが失敗する可能性があるのに対し、printf での使用 は良い習慣だと思います。残念ながら、その状況は実際に起こります。
MM

С99以降、Cの書式指定子と浮動小数点引数の型の一致はprintf、との間で一貫していscanfます。 これは、同じ形式指定子を使用しても、aによって書き込まれたデータ[f]printf()をが読み取れることを意味するわけではないことに注意してください[f]scanf()。一般に、で使用されたものと同じフォーマット指定子をscanf()使用してprintf()も、データ正常に読み取られません。たとえば、prinf()' "%d"形式指定子によって挿入できるスペースのパディング"%d"は、scanf()呼び出しで同じ形式指定子によってスキップされます。
Andrew Henle

16

scanfが指すデータのサイズを&d正しく満たすには、がそれを知る必要がありますが、可変個関数は浮動小数点数を倍精度浮動小数点数に昇格させるので(理由は完全にはわかりません)、printf常にを取得しdoubleます。


1
可変個引数関数は、渡されるすべてのパラメーターの正確な型とサイズを知る必要があり、コンパイル時にこれを強制できないため、非常に脆弱です。変数のタイプが間違っていると、間違った値が読み取られます。サイズが間違っていると、その後のすべての変数も誤って読み取られます。2つの異なるサイズのフロートを渡すことができると、あらゆる種類の厄介で見逃しやすい問題が発生します。
mwfearnley 2016年

7

それ以外の場合、scanfはdoubleより小さいサイズのfloatへのポインターを渡していると見なし、不正な値を返します。


2

Cの式でfloatまたはdoubleの値を使用すると、とにかくdoubleの値になるため、printfは違いを識別できません。一方、doubleへのポインタは、floatへのポインタとは異なるものとしてscanfに明示的に通知する必要があります。これは、ポインタが指すことが重要であるためです。


5
フロートは、doubleに変換され、この場合、引数は可変長引数リストの一部であるため、フロートは常にCのdouble型に変換されていません
ロバート・ギャンブル

1
C言語の先行標準バージョンでは、式のfloat値が自動的に昇格さdoubleれました。その規則は標準Cで放棄されました。通常、式ではfloat昇格さdoubleれません。これはdouble、可変個引数として渡された場合にのみ昇格されます。これは、この場合に起こります。
AnT 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.