Qual è la differenza tra printf () e put () in C?


176

So che puoi stampare con printf()e puts(). Vedo anche che printf()ti consente di interpolare le variabili e fare la formattazione.

È puts()semplicemente una versione primitiva di printf(). Dovrebbe essere usato per ogni possibile printf()senza interpolazione di stringhe?



48
Solo una nota sull'uso di printf anziché put: mai e poi mai fare un printf(variable)per stampare una stringa. Usa puts(variable)o printf("%s', variable). C'è un rischio per la sicurezza nell'uso di una stringa di formato variabile: se la variabile può essere scritta da un utente malintenzionato, può attaccare il programma utilizzando le stringhe di formato.
Zan Lynx,

Risposte:


141

putsè più semplice di printfma tieni presente che il primo aggiunge automaticamente una nuova riga. Se non è quello che vuoi, puoi fputsusare la stringa per stdout o uso printf.


8
Penso che sia anche importante menzionare gli argomenti aggiuntivi che printf prende per aggiungere ulteriori variabili nella stringa emessa.
Erutan409,

99

(Questo è sottolineato in un commento di Zan Lynx, ma penso che meriti una risposta, dato che la risposta accettata non lo menziona).

La differenza essenziale tra puts(mystr);e printf(mystr);è che in quest'ultima l'argomento viene interpretato come una stringa di formattazione . Il risultato sarà spesso lo stesso (tranne che per il ritorno a capo aggiunto) se la stringa non contiene caratteri di controllo ( %), ma se non si può fare affidamento su quella (se mystrè una variabile invece di un letterale) si dovrebbe non usarlo.

Quindi, è generalmente pericoloso, e concettualmente sbagliato , passare una stringa dinamica come singolo argomento di 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

Lo stesso vale per fputsvs fprintf(ma fputsnon aggiunge la nuova riga).


In che modo l'utilizzo printf()sarebbe meno efficiente? In fase di esecuzione? Al momento della compilazione?
Franklin,

10
@franklin in fase di esecuzione, perché printfdeve analizzare la stringa di formato. Tuttavia, questo dovrebbe essere normalmente irrilevante. Inoltre, un compilatore intelligente potrebbe ottimizzarlo e sostituire la printfchiamata aputs
leonbloy

33

Oltre alla formattazione, putsrestituisce un numero intero non negativo in caso di esito positivo o in EOFcaso di esito negativo ; while printfrestituisce il numero di caratteri stampati (escluso il null finale).


16

In casi semplici, il compilatore converte le chiamate printf()in chiamate in puts().

Ad esempio, il seguente codice verrà compilato nel codice assembly che mostrerò dopo.

#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

In questo esempio, ho usato GCC versione 4.7.2 e ho compilato il sorgente con gcc -o hello hello.c.


9
E che dire della nuova linea che mette i posti in stdout?
zubergu,

1
Avrebbe dovuto essere printf("Hello world!\n");gcc in effetti lo traduce in put. Dato che è un vecchio messaggio, lo modificherò da solo.
Rafael Almeida,

2
Come hai letto il codice assembly dopo aver compilato il codice C?
Koray Tugay,

3
@KorayTugay: l' -save-tempsopzione per gcc lo fa
schaiba,

Puoi anche usare uno strumento come gdb per disassemblare un binario.
Ivan Kaloyanov,

10

Giusto, printfpotrebbe essere pensato come una versione più potente di puts. printfoffre la possibilità di formattare le variabili per l'output utilizzando identificatori di formato, come %s, %d, %lf, ecc ...


10

Nella mia esperienza, printf()trasporta più codice che puts()indipendentemente dalla stringa di formato.

Se non ho bisogno della formattazione, non lo uso printf. Tuttavia, fwritea stdoutlavori molto più veloce di puts.

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

Nota: per commenti, '\ 0' è una costante intera. L'espressione corretta dovrebbe essere sizeof(char)come indicato dai commenti.


2
"fwrite to stdout funziona molto più velocemente di quanto si pensi." - Quale potrebbe essere la ragione?
Antony Hatchkins,

6
@AntonyHatchkins In genere non è "molto" più veloce. put (), tuttavia, deve eseguire una chiamata strlen () ogni volta sulla stringa, mentre se la dimensione è nota con fwrite () può essere evitata. È praticamente l'unico vero contributo a una differenza di prestazioni.
Wiz,

8
Questa risposta non è corretta '\0'ha tipo int, quindi sulla maggior parte dei sistemi verrà stampato Using fwrit. Se vuoi stampare 1 byte in meno, basta usare 1. sizeof (char), che è probabilmente quello che volevi qui, è garantito per essere 1.
Bradley Garagan

8
int puts(const char *s);

put () scrive la stringa se una nuova riga finale su stdout.

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

La funzione printf () scrive l'output su stdout, sotto il controllo di una stringa di formato che specifica come vengono convertiti gli argomenti successivi per l'output.

Userò questa opportunità per chiederti di leggere la documentazione.


5

la funzione printf () viene utilizzata per stampare sia le stringhe che le variabili sullo schermo mentre la funzione put () consente solo di stampare una stringa solo sullo schermo.


2

putsè la scelta semplice e aggiunge una nuova riga alla fine e printfscrive l'output da una stringa formattata.

Vedere la documentazione per puts e per printf.

Consiglierei di usare solo printfperché questo è più coerente del metodo di commutazione, cioè se si sta eseguendo il debug è meno doloroso cercare in tutti i file di stampa di putse printf. La maggior parte delle volte si desidera produrre anche una variabile nelle stampe, quindi putsviene utilizzata principalmente nel codice di esempio.


1

Quando si confronta puts()e printf(), anche se il loro consumo di memoria è quasi lo stesso, puts()richiede più tempo rispetto a printf().


Per favore aggiungi qualche spiegazione alla tua risposta in modo che altri possano imparare da essa - hai fonti affidabili per tale affermazione? O alcuni motivi per spiegare questa differenza?
Nico Haase,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.