printfのdoubleの正しい書式指定子


482

doubleprintfの正しい形式指定子は何ですか?それがある%fか、それがありますか%lf?だと%f思いますが、よくわかりません。

コードサンプル

#include <stdio.h>

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

19
C89ライブラリに悩まされている場合、"%lf"は未定義です。C99およびC11ライブラリでは、と同じであると定義されています"%f"
pmg 2012

1
あなたのバリアントは、これまでにないほど正確です。%lfの正しい形式指定子ですdouble。しかし、それはC99でそうなりました。その前に使用する必要がありました%f
AnTは2016年

回答:


626

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

これは、printfフォーマット文字列がフォーマット文字列scanf(およびfscanfなど)と大幅に異なる1つの場所であることに注意してください。出力の場合、を渡します。可変パラメーターとして渡されると、からfloatに昇格しdoubleます。入力の場合は、昇格されていないポインターを渡すのでscanf、a floatまたはa のどちらを読みたいかを伝える必要がありますdouble。したがって、forはscanf%faを読みたいことfloat%lf意味し、a double(および、価値は、のためにlong double、使用%Lfのいずれかのためprintfscanf)。


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


8
なお、g++不良品%lfでコンパイル-Wall -Werror -pedanticerror: ISO C++ does not support the ‘%lf’ gnu_printf format
kynan

2
@kynan:その場合(少なくとも現在のバージョンのg ++​​を想定している場合)、それはg ++のバグです。C89 / 90およびC ++ 98/03の場合、許可lは拡張機能でした。C99 / 11およびC ++ 11標準では、それを可能にする実装が必要です。
Jerry Coffin

1
不思議なことに、scanf ない希望doubleSで表される%lf:それはそれは期待と文句を言いfloat *、見つかったdouble *だけで%f
Eric Dand

1
@JerryCoffin g ++のデフォルトは引き続きg ++ 98モード
MM

5
@EricDandそれのためscanfので、それが読み何を保存する場所へのポインタを取る必要があり、一方、スペースが尖っ-にされているどのように大きな知っているprintf「デフォルト引数のプロモーションが」として両端を平均値そのものをとり、そしてdoubleので、S lであります基本的にオプションです。
TripeHound 2015

63

与えられたC99の標準(すなわち、N1256用のfprintf(のprintf、sprintfの、...)やscanf関数:ドラフト)、ルールは、関数の種類によって異なります。

抽出された関連パーツは次のとおりです。

序文

この第2版は、ISO / IEC 9899 / COR1:1994、ISO / IEC 9899 / AMD1:1995、およびISO / IEC 9899 / COR2:1996によって修正および修正された、第1版のISO / IEC 9899:1990を取り消して置き換えます。前版からの主な変更点は次のとおりです。

  • %lf で使用できる変換指定子 printf

7.19.6.1 fprintf関数

7長さ修飾子とその意味は次のとおりです。

l(エル)(...)が後続のa、A、e、E、f、F、g、またはG変換指定子に影響しないことを指定します。

L次のa、A、e、E、f、F、g、またはG変換指定子がlong double引数に適用されることを指定します。

に指定されたものと同じルールfprintfprintfsprintfおよび同様の関数に適用されます。

7.19.6.2 fscanf関数

11長さ修飾子とその意味は次のとおりです。

l(エル)次の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 ->ダブル
  • %Lf ->ロングダブル。

そしてfscanfそれは:

  • %f ->フロート
  • %lf ->ダブル
  • %Lf ->ロングダブル。

25

それは%f%gまたは%e数値をどのようにフォーマットするかによって異なります。詳細はこちらをご覧ください。l修飾子はで必要とされるscanfdouble、しかし、NOT IN printf


1
-1:(l小文字)修飾子は整数型(cplusplus.com/reference/clibrary/cstdio/printf)用でありL、浮動小数点型用です。さらに、L修飾子はlong doubleプレーンではなくを期待しdoubleます。
user470379 '19年

10
user470379:では、私の答えとの矛盾はどこにあるのでしょうか?のためにl必要ではないことを私は言ったことはありません。printfdouble
vitaut

16

形式%lfは、使用したとおりのの完全に正しいprintf形式ですdouble。コードに問題はありません。

形式%lfin printfは、C言語の古い(C99より前の)バージョンではサポートされていなかったためdouble、in printfとの形式指定子間に表面的な「矛盾」が生じていましたscanf。その表面的な矛盾はC99で修正されました。

あなたが使用する必要はありません%lfdoubleの中でprintf%f必要に応じて使用することもできます(%lfおよびと%f同等ですprintf)。しかし、現代のCにそれが使用することを好むために完璧な理にかなっている%ffloat%lfdouble%Lflong double一貫の両方で、printfscanf


ではscanf()"%f""%lf"一致しfloat *, double *ていない、float, doubleとして最後の行で暗示。
chux-モニカを復活させる

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.