Por que é scanf()
necessário que l
"in" %lf
ao ler a double
, quando printf()
" %f
" possa ser usado, independentemente de seu argumento ser a double
ou a float
?
Código de exemplo:
double d;
scanf("%lf", &d);
printf("%f", d);
c
scanf
length-modifiers
raldi
fonte
fonte
&
operador unário , o resultado dessa operação é um ponteiro para o local de armazenamento da variável na memória. É esse ponteiro que é passado parascanf
.Respostas:
Porque C promoverá flutuadores para dobras para funções que recebem argumentos variáveis. Os ponteiros não são promovidos a nada, então você deve usar
%lf
,%lg
ou%le
(ou%la
no C99) para ler em dobro.fonte
Desde С99, a correspondência entre especificadores de formato e tipos de argumento de ponto flutuante em C é consistente entre
printf
escanf
. Isto é%f
parafloat
%lf
paradouble
%Lf
paralong double
Acontece que quando argumentos do tipo
float
são passados como parâmetros variados, esses argumentos são implicitamente convertidos em tipodouble
. Esta é a razão pela qual emprintf
especificadores de formato%f
e%lf
são equivalentes e intercambiáveis. Emprintf
você pode "usar de forma cruzada"%lf
comfloat
ou%f
comdouble
.Mas não há razão para realmente fazer isso na prática. Não use
%f
paraprintf
argumentos do tipodouble
. É um hábito generalizado nascido em C89 / 90 vezes, mas é um mau hábito. Use%lf
noprintf
paradouble
e manter%f
reservados parafloat
argumentos.fonte
%f
no printf é um bom hábito, pois seu código sempre funciona, enquanto o uso%lf
pode falhar se o compilador não tiver uma biblioteca compatível com C99. Infelizmente essa situação acontece na realidade.printf
escanf
. Observe que isso não implica que o uso do mesmo especificador de formato signifique que os dados gravados por a[f]printf()
possam ser lidos[f]scanf()
. Em geral, o uso do mesmo especificador de formatoscanf()
usado porprintf()
ele não lerá os dados com êxito. Por exemplo, preenchimento de espaço que pode ser inserido por umprinf()
's"%d"
especificador de formato será ignorado pelo mesmo"%d"
especificador de formato em umascanf()
chamada.scanf
precisa saber o tamanho dos dados que estão sendo apontados&d
para preenchê-los adequadamente, enquanto as funções variadas promovem flutuações para dobras (sem saber exatamente o porquê), portanto,printf
sempre está obtendo umdouble
.fonte
Porque, caso contrário, o scanf pensará que você está passando um ponteiro para um ponto flutuante com tamanho menor que o dobro e retornará um valor incorreto.
fonte
Usar um valor flutuante ou duplo em uma expressão C resultará em um valor que é um duplo de qualquer maneira, portanto printf não pode dizer a diferença. Enquanto um ponteiro para um duplo deve ser explicitamente sinalizado para scanf como distinto de um ponteiro para flutuar, porque o que o ponteiro aponta é o que importa.
fonte
float
valores eram automaticamente promovidos paradouble
em expressões. Essa regra foi abandonada no padrão C. Geralmente,float
não é promovida paradouble
em expressões. Ele só é promovido paradouble
quando passado como argumento variável, que é o que acontece neste caso.