Por que scanf () precisa de "% lf" para o dobro, quando printf () está bem com apenas "% f"?


179

Por que é scanf()necessário que l"in" %lfao ler a double, quando printf()" %f" possa ser usado, independentemente de seu argumento ser a doubleou a float?

Código de exemplo:

double d;
scanf("%lf", &d);
printf("%f", d);

1
Eu não entendo o que você quer dizer com POINTER aqui. Em scanf nós só passar e endereço da variável (ou seja) então onde está o ponteiro

7
@deetchanya Em C, quando você "pega o endereço de" uma variável com o &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 para scanf.
Zwol

esta é outra publicação sobre esse stackoverflow.com/questions/9291348/…
vimalpt 22/09/14

Respostas:


207

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, %lgou %le(ou %lano C99) para ler em dobro.


26

Desde С99, a correspondência entre especificadores de formato e tipos de argumento de ponto flutuante em C é consistente entre printfe scanf. Isto é

  • %f para float
  • %lf para double
  • %Lf para long double

Acontece que quando argumentos do tipo floatsão passados ​​como parâmetros variados, esses argumentos são implicitamente convertidos em tipo double. Esta é a razão pela qual em printfespecificadores de formato %fe %lfsão equivalentes e intercambiáveis. Em printfvocê pode "usar de forma cruzada" %lfcom floatou %fcom double.

Mas não há razão para realmente fazer isso na prática. Não use %fpara printfargumentos do tipo double. É um hábito generalizado nascido em C89 / 90 vezes, mas é um mau hábito. Use %lfno printfpara doublee manter %freservados para floatargumentos.


1
Eu diria que usar %fno printf é um bom hábito, pois seu código sempre funciona, enquanto o uso %lfpode falhar se o compilador não tiver uma biblioteca compatível com C99. Infelizmente essa situação acontece na realidade.
22316 MM

Desde С99, a correspondência entre especificadores de formato e tipos de argumento de ponto flutuante em C é consistente entre printfe scanf. 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 formato scanf()usado por printf()ele não lerá os dados com êxito. Por exemplo, preenchimento de espaço que pode ser inserido por um prinf()'s "%d"especificador de formato será ignorado pelo mesmo "%d"especificador de formato em uma scanf()chamada.
Andrew Henle

16

scanfprecisa saber o tamanho dos dados que estão sendo apontados &dpara preenchê-los adequadamente, enquanto as funções variadas promovem flutuações para dobras (sem saber exatamente o porquê), portanto, printfsempre está obtendo um double.


1
Uma função variadica é muito frágil, porque precisa saber o tipo e tamanho exato de todos os parâmetros passados ​​para ela, e não pode impor isso em tempo de compilação. Se uma variável for do tipo errado, o valor errado será lido; se o tamanho estiver errado, todas as variáveis ​​posteriores também serão mal interpretadas. Se dois tamanhos diferentes de flutuador pudessem ser passados, isso causaria todos os tipos de problemas desagradáveis ​​e fáceis de perder.
precisa saber é o seguinte

7

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.


2

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.


5
flutuador é convertido para um casal , neste caso, porque os argumentos são parte de uma lista de argumentos de comprimento variável, bóias nem sempre são convertidos em duplas em C.
Robert Gamble

1
Nas versões pré-padrão da linguagem C, os floatvalores eram automaticamente promovidos para doubleem expressões. Essa regra foi abandonada no padrão C. Geralmente, floatnão é promovida para doubleem expressões. Ele só é promovido para doublequando passado como argumento variável, que é o que acontece neste caso.
AnT
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.