Printfのdouble
の正しいフォーマット指定子は何ですか? %f
ですか、それとも%lf
ですか。 %f
だと思いますが、よくわかりません。
#include <stdio.h>
int main()
{
double d = 1.4;
printf("%lf", d); // Is this wrong?
}
"%f"
は、doubleの(または少なくとも1つの)正しい形式です。そこにisfloat
のフォーマットはありません。float
をprintf
に渡そうとすると、double
に昇格されるためですprintf
はそれを受け取ります1。 "%lf"
は現在の標準でも受け入れられます。l
は、(特に)f
変換指定子が続く場合、効果がないと指定されます。
これは、printf
フォーマット文字列がscanf
(およびfscanf
など)フォーマット文字列と大幅に異なる1つの場所であることに注意してください。出力の場合、valueを渡します。これは、可変引数として渡されたときにfloat
からdouble
に昇格されます。入力にはpointerを渡しますが、これは昇格されないため、scanf
を読むかfloat
を読むかをdouble
に伝える必要があります。 scanf
の場合、%f
はfloat
を読みたいことを意味し、%lf
はdouble
を読みたいことを意味しますlong double
、printf
またはscanf
のいずれかに%Lf
を使用します。
1. C99、§6.5.2.2/ 6:「呼び出された関数を示す式がプロトタイプを含まない型を持つ場合、整数のプロモーションは各引数で実行され、float型の引数はdoubleに昇格されます。これらはデフォルト引数プロモーションと呼ばれます。」 C++では、言葉遣いは多少異なります(たとえば、「プロトタイプ」という単語を使用しません)が、効果は同じです。すべての可変引数は、関数が受け取る前にデフォルトのプロモーションを実行します。
C99 標準(つまり、N1256 _ドラフト)を考えると、規則は関数の種類によって異なります:fprintf(printf、sprintf、...)またはscanf。
関連する部分を抜粋します。
はじめに
この第2版は、ISO/IEC 9899/COR 1:1994、ISO/IEC 9899/AMD 1:1995、およびISO/IEC 9899/COR 2:1996によって修正および修正された、第1版ISO/IEC 9899:1990を取り消して置き換えます。前版からの主な変更点は次のとおりです。
%lf
変換指定子はprintf
で使用できます7.19.6.1
fprintf
関数7 長さ修飾子とその意味は次のとおりです。
l(ell)(...)が後続のa、A、e、E、f、F、g、またはG変換指定子に影響を与えないことを指定します。
L後に続くa、A、e、E、f、F、g、またはG変換指定子がlong double引数に適用されることを指定します。
fprintf
に指定されているのと同じ規則が、printf
、sprintf
、および類似の関数にも適用されます。
7.19.6.2
fscanf
関数11 長さ修飾子とその意味は次のとおりです。
l(ell)次のa、A、e、E、f、F、g、またはG変換指定子が、doubleへの型ポインタを持つ引数に適用されることを指定します。
L後に続くa、A、e、E、f、F、g、またはG変換指定子が、long doubleへの型ポインタを持つ引数に適用されることを指定します。
12 変換指定子とその意味は次のとおりです。a、e、f、gオプションで符号付きの浮動小数点数と一致します。(...)
14 変換指定子A、E、F、G、およびXも有効であり、それぞれa、e、f、g、およびxと同じ動作をします。
手短に言えば、fprintf
では、以下の指定子と対応する型が指定されています。
%f
- > double%Lf
- > long double.fscanf
の場合は、
%f
- > float%lf
- > double%Lf
- > long double.数値の書式設定方法によって、%f
、%g
、または%e
になります。詳しくは こちら をご覧ください。 l
修飾子は、scanf
と一緒にdouble
に必要ですが、printf
には必要ありません。
printf
の正しいdouble
フォーマットは、使用したとおりの%lf
です。コードに問題はありません。
printf
のフォーマット%lf
は、double
のprintf
のフォーマット指定子とscanf
のフォーマット指定子との間に見かけ上の「矛盾」を生じさせた古い(C99より前の)バージョンのC言語ではサポートされていません。その表面的な矛盾はC99で修正されました。
そのため、現代のCでは、float
とdouble
の両方で、%f
をprintf
と、%lf
をscanf
と、そして%Lf
をlong double
と一緒に使用することを選択するのが理想的です。
%Lf
(大文字のL
に注意)は フォーマット指定子 / long doubles のためのものです。
普通のdoubles
に対しては、%e
、%E
、%f
、%g
、%G
のどちらでも構いません。