web-dev-qa-db-ja.com

Printfのdoubleの正しいフォーマット指定子

Printfのdoubleの正しいフォーマット指定子は何ですか? %fですか、それとも%lfですか。 %fだと思いますが、よくわかりません。

コードサンプル

#include <stdio.h>

int main()
{
   double d = 1.4;
   printf("%lf", d); // Is this wrong?
}
414
Leopard

"%f"は、doubleの(または少なくとも1つの)正しい形式です。そこにisfloatのフォーマットはありません。floatprintfに渡そうとすると、doubleに昇格されるためですprintfはそれを受け取ります1"%lf"は現在の標準でも受け入れられます。lは、(特に)f変換指定子が続く場合、効果がないと指定されます。

これは、printfフォーマット文字列がscanf(およびfscanfなど)フォーマット文字列と大幅に異なる1つの場所であることに注意してください。出力の場合、valueを渡します。これは、可変引数として渡されたときにfloatからdoubleに昇格されます。入力にはpointerを渡しますが、これは昇格されないため、scanfを読むかfloatを読むかをdoubleに伝える必要があります。 scanfの場合、%ffloatを読みたいことを意味し、%lfdoubleを読みたいことを意味しますlong doubleprintfまたはscanfのいずれかに%Lfを使用します。


1. C99、§6.5.2.2/ 6:「呼び出された関数を示す式がプロトタイプを含まない型を持つ場合、整数のプロモーションは各引数で実行され、float型の引数はdoubleに昇格されます。これらはデフォルト引数プロモーションと呼ばれます。」 C++では、言葉遣いは多少異なります(たとえば、「プロトタイプ」という単語を使用しません)が、効果は同じです。すべての可変引数は、関数が受け取る前にデフォルトのプロモーションを実行します。

561
Jerry Coffin

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に指定されているのと同じ規則が、printfsprintf、および類似の関数にも適用されます。

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.
54
mloskot

数値の書式設定方法によって、%f%g、または%eになります。詳しくは こちら をご覧ください。 l修飾子は、scanfと一緒にdoubleに必要ですが、printfには必要ありません。

18
vitaut

printfの正しいdoubleフォーマットは、使用したとおりの%lfです。コードに問題はありません。

printfのフォーマット%lfは、doubleprintfのフォーマット指定子とscanfのフォーマット指定子との間に見かけ上の「矛盾」を生じさせた古い(C99より前の)バージョンのC言語ではサポートされていません。その表面的な矛盾はC99で修正されました。

そのため、現代のCでは、floatdoubleの両方で、%fprintfと、%lfscanfと、そして%Lflong doubleと一緒に使用することを選択するのが理想的です。

9
AnT

%Lf(大文字のLに注意)は フォーマット指定子 / long doubles のためのものです。

普通のdoublesに対しては、%e%E%f%g%Gのどちらでも構いません。

7