Cに次のようなコードがあるとしましょう。
double var;
scanf("%lf", &var);
printf("%lf", var);
printf("%f", var);
Stdin変数「var」から読み取り、stdout「var」に2回出力します。私はそれがstdinからdouble変数を読み取る方法だと理解していますが、私の質問は次のとおりです:
printf
やscanf
などの変数引数関数の場合、引数は昇格されます。たとえば、より小さい整数型はint
に昇格され、float
はdouble
に昇格されます。
scanf
はポインターのパラメーターを受け取るため、プロモーションルールは有効になりません。 %f
にはfloat*
を、%lf
にはdouble*
を使用する必要があります。
printf
はfloat
引数を参照することはありません。float
は常にdouble
に昇格されます。形式指定子は%f
です。しかし、C99は%lf
はprintf
の%f
と同じだとも言っています。
C99§7.19.6.1
fprintf
関数
l
(ell)次のd
、i
、o
、u
、x
、またはX
変換指定子がlong int
またはunsigned long int
引数に適用されることを指定します。次のn
変換指定子がlong int
引数へのポインターに適用されること。次のc
変換指定子がwint_t
引数に適用されること。次のs
変換指定子がwchar_t
引数へのポインターに適用されること。またはは、後続のa
、A
、e
、E
、f
、F
、g
、またはG
変換指定子には影響しません。
float
がprintf
に渡されると、自動的にdouble
に変換されます。これはデフォルト引数プロモーションの一部であり、これは主に歴史的な理由で、可変パラメーターリスト(...
を含む)を持つ関数に適用されます。したがって、float
、%f
の「自然な」指定子は、double
引数で動作する必要があります。したがって、printf
の%f
および%lf
指定子は同じです。両方ともdouble
値を取ります。
scanf
が呼び出されると、直接値ではなくポインターが渡されます。 float
へのポインターはdouble
へのポインターに変換されません(ポインタータイプを変更しても、ポイント先のオブジェクトは変更できないため、これは機能しませんでした)。したがって、scanf
の場合、%f
の引数はfloat
へのポインターでなければならず、%lf
の引数はdouble
へのポインターでなければなりません。
マニュアルページを読む限り、scanfは、長さ修飾子 'l'が(浮動小数点の場合)引数がfloat型ではなくdouble型であることを示すため、 'lf、le、lg'を使用できると述べています。
印刷に関しては、公式には、マニュアルでは「l」は整数型にのみ適用されると書かれています。そのため、一部のシステムまたは一部の標準ではサポートされていない場合があります。たとえば、gcc -Wall -Wextra -pedantic
でコンパイルすると、次のエラーメッセージが表示されます
a.c:6:1: warning: ISO C90 does not support the ‘%lf’ gnu_printf format [-Wformat=]
そのため、標準が構文をサポートしているかどうかを再確認することをお勧めします。
結論として、「%lf」で読み、「%f」で印刷するとします。