it-roy-ru.com

Правильный спецификатор формата для double в printf

Каков правильный спецификатор формата для double в printf? Это %f или %lf? Я считаю, что это %f, но я не уверен.

Пример кода

#include <stdio.h>

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

"%f" - это (или хотя бы один) правильный формат для двойного числа. Существует is нет формата для float, потому что если вы попытаетесь передать float в printf, он будет повышен до double до того, как printf получит его1, "%lf" также допустим в соответствии с текущим стандартом - l определено как не имеющее эффекта, если за ним следует спецификатор преобразования f (среди прочих).

Обратите внимание, что это то место, где строки формата printf существенно отличаются от строк формата scanffscanf и т.д.). Для вывода вы передаете значение, которое будет преобразовано из float в double при передаче в качестве параметра переменной. Для ввода вы передаете указатель, который не повышается, поэтому вы должны сообщить scanf, хотите ли вы читать float или double, поэтому для scanf, %f означает, что вы хотите прочитать float и %lf означает, что вы хотите прочитать double (и, для чего бы это ни стоило, для long double, вы используете %Lf для printf или scanf).


1. C99, §6.5.2.2/6: "Если выражение, которое обозначает вызываемую функцию, имеет тип, который не включает в себя прототип, целочисленные преобразования выполняются для каждого аргумента, а аргументы, имеющие тип float, повышаются до двойного. Это называется продвижением аргументов по умолчанию. " В C++ формулировка несколько иная (например, он не использует слово "прототип"), но эффект тот же: все переменные параметры проходят промоакции по умолчанию, прежде чем они будут получены функцией.

543
Jerry Coffin

Учитывая стандарт C99 (а именно: N1256 черновик), правила зависят от вида функции: fprintf (printf, sprintf, ...) или зсапЕ.

Вот соответствующие извлеченные части:

Предисловие

Настоящее второе издание отменяет и заменяет первое издание, ISO/IEC 9899: 1990, с поправками и исправлениями, изложенными в ISO/IEC 9899/COR1: 1994, ISO/IEC 9899/AMD1: 1995 и ISO/IEC 9899/COR2: 1996. Основные изменения по сравнению с предыдущим изданием:

  • %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 применяется к длинному двойному аргументу.

Те же правила, которые указаны для fprintf, применяются к printf, sprintf и аналогичным функциям.

7.19.6.2 Функция fscanf

11 Модификаторы длины и их значения:

l (ell) Указывает, что (...), что следующий спецификатор преобразования a, A, e, E, f, F, g или G применяется к аргументу с типом указатель на двойной;

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. и х.

Короче говоря, для fprintf указываются следующие спецификаторы и соответствующие типы:

  • %f -> двойной
  • %Lf -> длинный двойной.

и для fscanf это:

  • %f -> float
  • %lf -> двойной
  • %Lf -> длинный двойной.
57
mloskot

Это может быть %f, %g или %e в зависимости от того, как вы хотите отформатировать число. Смотрите здесь для более подробной информации. Модификатор l требуется в scanf с double, но не в printf.

18
vitaut

Правильный формат printf для double - это %lf, именно так, как вы его использовали. В вашем коде нет ничего плохого.

Формат %lf в printf не поддерживался в старых (до C99) версиях языка C, что приводило к поверхностной "несогласованности" между спецификаторами формата для double в printf и scanf. Это поверхностное несоответствие было исправлено в C99.

Поэтому в современном C имеет смысл использовать %f с float, %lf с double и %Lf с long double последовательно как в printf, так и scanf.

9
AnT

%Lf (обратите внимание на заглавную букву L) --- это спецификатор формата для длинные числа удваиваются .

Для простого doubles подойдут %e, %E, %f, %g или %G.

7
Frédéric Hamidi