Dlaczego scanf()
potrzebuje l
„ %lf
” podczas czytania double
, kiedy printf()
może używać „ %f
” bez względu na to, czy jego argumentem jest double
a float
?
Przykładowy kod:
double d;
scanf("%lf", &d);
printf("%f", d);
c
scanf
length-modifiers
raldi
źródło
źródło
&
operatorem jednoargumentowym , wynikiem tej operacji jest wskaźnik do miejsca przechowywania zmiennej w pamięci. Jest to wskaźnik, który jest przekazywanyscanf
.Odpowiedzi:
Ponieważ C będzie promować zmiennoprzecinkowe do podwójnych dla funkcji, które przyjmują zmienne argumenty. Wskaźniki nie są promowane do niczego, więc powinieneś być w użyciu
%lf
,%lg
czy%le
(lub%la
w C99), aby czytać w deblu.źródło
Od czasu С99 dopasowanie specyfikatorów formatu do typów argumentów zmiennoprzecinkowych w C jest spójne między
printf
iscanf
. To jest%f
dlafloat
%lf
dladouble
%Lf
dlalong double
Zdarza się tak, że gdy argumenty typu
float
są przekazywane jako parametry variadic, takie argumenty są domyślnie konwertowane na typdouble
. To jest powód, dlaczego wprintf
formacie specyfikatorami%f
i%lf
są równoważne i wymienne. Wprintf
„cross-use”%lf
zfloat
lub%f
zdouble
.Ale nie ma powodu, aby robić to w praktyce. Nie stosować
%f
doprintf
argumentów typudouble
. Jest to powszechny nawyk urodzony w C89 / 90 razy, ale jest to zły nawyk. Zastosowanie%lf
wprintf
zadouble
i ciągle%f
zarezerwowane dlafloat
argumentów.źródło
%f
w printf jest dobrym nawykiem, ponieważ wtedy twój kod zawsze działa, podczas gdy używanie%lf
może się nie powieść, jeśli kompilator nie ma biblioteki zgodnej z C99. Niestety taka sytuacja zdarza się w rzeczywistości.printf
iscanf
. Zauważ, że nie oznacza to, że użycie tego samego specyfikatora formatu oznacza, że dane zapisane przez a[f]printf()
mogą być odczytane przez[f]scanf()
. Ogólnie rzecz biorąc, użycie tego samego specyfikatora formatu,scanf()
który był używany przezprintf()
, nie spowoduje pomyślnego odczytania danych. Na przykład, przestrzeń wyściółka, która może być włożona przezprinf()
„s"%d"
formatu specyfikatora zostaną pominięte przez tego samego"%d"
formatu specyfikatora wscanf()
rozmowy.scanf
musi znać rozmiar danych wskazywanych przez,&d
aby je poprawnie wypełnić, podczas gdy funkcje variadic promują zmienne do podwójnych (nie do końca pewni dlaczego), więcprintf
zawsze dostajedouble
.źródło
Ponieważ inaczej scanf pomyśli, że przekazujesz wskaźnik do liczby zmiennoprzecinkowej, która jest mniejsza niż podwójna, i zwróci niepoprawną wartość.
źródło
Użycie wartości zmiennoprzecinkowych lub podwójnych w wyrażeniu C spowoduje, że i tak będzie to wartość podwójna, więc printf nie może odróżnić różnicy. Podczas gdy wskaźnik do podwójnej liczby musi być wyraźnie zasygnalizowany, aby skanować jako odrębny od wskaźnika do liczby zmiennoprzecinkowej, ponieważ liczy się to, na co wskazuje wskaźnik.
źródło
float
wartości języka były automatycznie promowanedouble
w wyrażeniach. Ta zasada została porzucona w standardzie C. Zasadniczofloat
nie jest promowanadouble
w wyrażeniach. Awansuje się tylkodouble
wtedy, gdy zostanie przekazany jako argument variadic, co dzieje się w tym przypadku.