web-dev-qa-db-ja.com

printf()が「%f」だけで十分なのに、なぜscanf()がdoubleに対して「%lf」を必要とするのですか?

lを読み取るときにscanf()が "%lf"でdoubleを必要とするのは、なぜprintf()がその引数がdoubleであるかfloatであるかに関係なく "%f"を使用できるからですか?

サンプルコード:

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

Cは、可変引数を取る関数のfloatをdoubleにプロモートするためです。ポインターは何にも昇格されないので、%lf%lg、または%le(またはC99では%la)を使用してダブルで読み取る必要があります。

198
MSN

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

  • float%f
  • double%lf
  • %Lf for long double

タイプfloatの引数が可変引数として渡されると、そのような引数は暗黙的にタイプdoubleに変換されます。これが、printf形式指定子%f%lfが同等で互換性がある理由です。 printfでは、float%lfまたはdouble%fを「相互使用」できます。

しかし、実際に実際に行う理由はありません。タイプprintfdouble引数に%fを使用しないでください。それは、C89/90時代に生まれた広範な習慣ですが、悪い習慣です。 printfにはdouble%lfを使用し、float引数には%fを予約しておいてください。

23
AnT

scanfは、&dが指すデータのサイズを認識して適切に入力する必要がありますが、可変長関数はfloatをdoubleに昇格します(理由は完全にはわかりません)。したがって、printfは常にdoubleを取得します。

16
Tanktalus

そうしないと、scanfは、doubleよりも小さいサイズのfloatにポインターを渡していると見なし、誤った値を返します。

7
Jim Buck

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

2
fcw