Pergunta

Qual é o especificador de formato correto para double em printf? É isso %f ou é %lf? Eu acredito que é %f, mas eu não tenho certeza.

Exemplo de código

#include <stdio.h>

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

Solução

"%f" é o (ou pelo menos um) formato correto para um dobro. Lá é Sem formato para um float, porque se você tentar passar um float para printf, será promovido a double antes da printf recebe1. "%lf" também é aceitável sob o padrão atual - o l é especificado como não tendo efeito se seguido pelo f Especificador de conversão (entre outros).

Observe que este é um lugar que printf As seqüências de formato diferem substancialmente de scanf (e fscanf, etc.) Formato Strings. Para produção, você está passando um valor, que será promovido de float para double Quando passado como um parâmetro variódico. Para a entrada que você está passando um ponteiro, que não é promovido, então você tem que dizer scanf Se você quer ler um float ou a double, então para scanf, %f significa que você quer ler um float e %lf significa que você quer ler um double (e, pelo que vale, para um long double, você usa %Lf para qualquer printf ou scanf).


1. C99, §6.5.2.2/6: "Se a expressão que denota a função chamada possui um tipo que não inclui um protótipo, as promoções inteiras são realizadas em cada argumento e os argumentos que têm o tipo de flutuação são promovidos para dobrar. Estes são chamados de promoções de argumentos padrão ". Em C ++, a redação é um pouco diferente (por exemplo, não usa a palavra "protótipo"), mas o efeito é o mesmo: todos os parâmetros variados passam por promoções padrão antes de serem recebidas pela função.

Outras dicas

Considerando a C99 padrão (a saber, o N1256 rascunho), as regras dependem do tipo de função: fprintf (printf, sprintf, ...) ou scanf.

Aqui estão as peças relevantes extraídas:

Prefácio

Esta segunda edição cancela e substitui a primeira edição, ISO/IEC 9899: 1990, conforme alterada e corrigida pela ISO/IEC 9899/COR1: 1994, ISO/IEC 9899/AMD1: 1995 e ISO/IEC 9899/COR2: 1996. As principais mudanças da edição anterior incluem:

  • %lf especificador de conversão permitido em printf

7.19.6.1 O fprintf função

7 Os modificadores de comprimento e seus significados são:

eu (Ell) especifica que (...) não tem efeito a seguir, especificador de conversão A, A, E, E, F, F, G ou G.

eu Especifica que a seguinte a, A, E, E, F, F, G ou G Specificador de conversão se aplica a um longo argumento duplo.

As mesmas regras especificadas para fprintf candidatar-se a printf, sprintf e funções semelhantes.

7.19.6.2 O fscanf função

11 Os modificadores de comprimento e seus significados são:

eu (Ell) especifica que (...) que um especificador de conversão A, A, E, E, F, F, G ou G se aplica a um argumento com o ponteiro do tipo para dobrar;

eu Especifica que a seguinte especificador de conversão A, A, E, E, F, F, G ou G se aplica a um argumento com ponteiro de tipo para o dobro longo.

12 Os especificadores de conversão e seus significados são: a, e, f, g corresponde a um número de ponto flutuante opcionalmente assinado, (...)

14 Os especificadores de conversão A, E, F, G e X também são válidos e se comportam da mesma forma que, respectivamente, A, E, F, G e X.

A longa história encurtar, para fprintf Os seguintes especificadores e tipos correspondentes são especificados:

  • %f -> duplo
  • %Lf -> Longo duplo.

e para fscanf isso é:

  • %f -> flutuar
  • %lf -> duplo
  • %Lf -> Longo duplo.

Pode ser %f, %g ou %e dependendo de como você deseja que o número seja formatado. Ver aqui para mais detalhes. o l O modificador é necessário em scanf com double, mas não em printf.

O correto printf formato para double é %lf, exatamente como você usou. Não há nada de errado com seu código.

Formato %lf dentro printf não foi apoiado nas versões antigas (pré-C99) da linguagem C, que criaram "inconsistência" superficial entre especificadores de formato para double dentro printf e scanf. Essa inconsistência superficial foi fixada em C99.

Então, no moderno C, faz todo o sentido preferir usar %f com float, %lf com double e %Lf com long double consistentemente em ambos printf e scanf.

%Lf (Observe o capital L) é o Especificador de formato por longas duplas.

Para simples doubles, qualquer %e, %E, %f, %g ou %G vai fazer.

Para o dobro, você pode simplesmente usar %lf ou você pode usar qualquer seguinte conforme sua preferência

%e ou %E Para valores em formato exponencial

%g ou %G para notação normal ou exponencial, o que for mais apropriado para sua magnitude.

Leia mais aqui Lista de todo especificador de formato em C

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top