Especificador de formato correto para duplo no printf
-
27-09-2019 - |
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?
}
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 emprintf
7.19.6.1 O
fprintf
função7 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ção11 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