Qual é a diferença entre printf () e puts () em C?


176

Eu sei que você pode imprimir com printf()e puts(). Também posso ver que printf()permite interpolar variáveis ​​e formatar.

É puts()apenas uma versão primitiva de printf(). Deve ser usado para todos os possíveis printf()sem interpolação de string?



47
Apenas uma observação sobre o uso de printf em vez de puts: nunca, faça um printf(variable)para imprimir uma string. Use puts(variable)ou printf("%s', variable). Há um risco de segurança ao usar uma sequência de formato variável: se a variável puder ser gravada por um invasor, eles poderão atacar o programa usando sequências de formato.
Zan Lynx

Respostas:


141

putsé mais simples que, printfmas lembre-se de que o primeiro anexa automaticamente uma nova linha. Se não é isso que você deseja, você pode fputsusar sua string para usar o stdout printf.


8
Eu acho que também é importante mencionar os argumentos adicionais que printf leva para adicionar variáveis ​​adicionais na string de saída.
Erutan409

99

(Isso é apontado em um comentário de Zan Lynx, mas acho que merece uma resposta - já que a resposta aceita não o menciona).

A diferença essencial entre puts(mystr);e printf(mystr);é que, no último, o argumento é interpretado como uma sequência de formatação . O resultado geralmente será o mesmo (exceto a nova linha adicionada) se a string não contiver caracteres de controle ( %), mas se você não puder confiar nisso (se mystrfor uma variável em vez de literal), não deverá usá-la.

Portanto, geralmente é perigoso - e conceitualmente errado - passar uma sequência dinâmica como argumento único de printf:

  char * myMessage;
  // ... myMessage gets assigned at runtime, unpredictable content
  printf(myMessage);  // <--- WRONG! (what if myMessage contains a '%' char?) 
  puts(myMessage);    // ok
  printf("%s\n",myMessage); // ok, equivalent to the previous, perhaps less efficient

O mesmo se aplica ao fputsvs fprintf(mas fputsnão adiciona a nova linha).


De que maneira o uso printf()seria menos eficiente? Em tempo de execução? Em tempo de compilação?
franklin

10
@ franklin em tempo de execução, porque printfprecisa analisar a string de formato. No entanto, isso normalmente deve ser irrelevante. Além disso, um compilador inteligente pode otimizar isso e substituir o printfputs
comando

33

Além da formatação, putsretorna um número inteiro não negativo se for bem-sucedido ou EOFse não for bem- sucedido; while printfretorna o número de caracteres impressos (não incluindo o nulo à direita).


16

Em casos simples, o compilador converte chamadas printf()em chamadas para puts().

Por exemplo, o código a seguir será compilado no código de montagem que mostro a seguir.

#include <stdio.h>
main() {
    printf("Hello world!");
    return 0;
}
push rbp
mov rbp,rsp
mov edi,str.Helloworld!
call dword imp.puts
mov eax,0x0
pop rbp
ret

Neste exemplo, usei a versão 4.7.2 do GCC e compilei a fonte gcc -o hello hello.c.


9
E a nova linha que coloca lugares no stdout?
Zubergu 12/09

1
Deveria ter sido printf("Hello world!\n");gcc de fato traduz isso para put. Como é uma mensagem antiga, eu mesma a editarei.
Rafael Almeida

2
Como você leu o código do assembly após compilar o código C?
Koray Tugay

3
@KorayTugay: a -save-tempsopção para gcc faz isso
schaiba

Você também pode usar uma ferramenta como o gdb para desmontar um binário.
Ivan Kaloyanov 24/12/19

10

Certo, printfpoderia ser pensado como uma versão mais poderosa do puts. printffornece a capacidade de formato variáveis para especificadores de formato de saída usando tais como %s, %d, %lf, etc ...


10

Na minha experiência, printf()carrega mais código do que puts()independentemente da string de formato.

Se não precisar de formatação, não o uso printf. No entanto, fwritepara stdouttrabalhar muito mais rápido que puts.

static const char my_text[] = "Using fwrite.\n";
fwrite(my_text, 1, sizeof(my_text) - sizeof('\0'), stdout);

Nota: por comentários, '\ 0' é uma constante inteira. A expressão correta deve ser a sizeof(char)indicada pelos comentários.


2
"fwrite to stdout funciona muito mais rápido que o put." - Qual poderia ser o motivo?
Antony Hatchkins

6
@AntonyHatchkins Normalmente não é "muito" mais rápido. O puts (), no entanto, precisa executar uma chamada strlen () toda vez em sua string, enquanto que se o tamanho for conhecido com fwrite (), ele poderá ser evitado. Esse é praticamente o único contribuidor real para uma diferença de desempenho.
Wiz

8
Esta resposta está incorreta. '\0'tem tipo int, portanto, na maioria dos sistemas, isso será impresso Using fwrit. Se você deseja imprimir uma menor byte, basta usar 1. sizeof (char), que é provável que você pretende aqui, é garantido para ser 1.
Bradley Garagan

8
int puts(const char *s);

puts () grava a string se uma nova linha no stdout.

int printf(const char *format, ...);

A função printf () grava a saída em stdout, sob o controle de uma sequência de formato que especifica como os argumentos subsequentes são convertidos para a saída.

Usarei esta oportunidade para solicitar que você leia a documentação.


5

a função printf () é usada para imprimir seqüências de caracteres e variáveis ​​na tela, enquanto a função puts () permite imprimir apenas uma sequência na tela.


2

puts é a escolha simples e adiciona uma nova linha no final e printf grava a saída de uma sequência formatada.

Consulte a documentação para puts e paraprintf .

Eu recomendaria usar apenas, printfpois isso é mais consistente do que o método de alternância, ou seja, se você estiver depurando, é menos trabalhoso pesquisar todos os printfs que putse printf. Na maioria das vezes você também deseja gerar uma variável em suas impressões, portanto putsé usado principalmente no exemplo de código.


1

Ao comparar puts()e printf(), embora o consumo de memória seja quase o mesmo, puts()leva mais tempo em comparação com printf().


Por favor, adicione alguma explicação à sua resposta para que outras pessoas possam aprender com ela - você tem fontes confiáveis ​​para essa reivindicação? Ou algumas razões para explicar essa diferença?
Nico Haase
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.