Was ist der Unterschied zwischen printf () und put () in C?

176

Ich weiß, dass Sie mit printf()und drucken können puts(). Ich kann auch sehen, printf()dass Sie damit Variablen interpolieren und formatieren können.

Ist puts()nur eine primitive Version von printf(). Sollte es für jede mögliche printf()ohne String-Interpolation verwendet werden?

Alex
quelle
47
Nur ein Hinweis zur Verwendung von printf anstelle von Puts: Machen Sie niemals einen printf(variable), um einen String zu drucken. Verwenden Sie puts(variable)oder printf("%s', variable). Die Verwendung einer Variablenformatzeichenfolge birgt ein Sicherheitsrisiko: Wenn die Variable von einem Angreifer geschrieben werden kann, kann er das Programm mithilfe von Formatzeichenfolgen angreifen.
Zan Lynx

Antworten:

141

putsist einfacher als, printfaber beachten Sie, dass die erstere automatisch eine neue Zeile anfügt. Wenn Sie dies nicht möchten, können Sie fputsIhre Zeichenfolge stdout oder verwenden printf.

Michael Kristofik
quelle
8
Ich denke, es ist auch wichtig, die zusätzlichen Argumente zu erwähnen, die printf zum Hinzufügen zusätzlicher Variablen zur ausgegebenen Zeichenfolge verwendet.
Erutan409
99

(Dies wird in einem Kommentar von Zan Lynx hervorgehoben, aber ich denke, es verdient eine Antwort - da die akzeptierte Antwort es nicht erwähnt).

Der wesentliche Unterschied zwischen puts(mystr);und printf(mystr);besteht darin, dass das Argument in letzterem als Formatierungszeichenfolge interpretiert wird . Das Ergebnis wird oft die gleichen ( mit Ausnahme der zusätzlichen Newline) , wenn die Zeichenfolge enthält keine Steuerzeichen ( %) , aber wenn Sie nicht darauf verlassen können (wenn mystrSie sollten eine Variable anstelle einer wörtlichen ist) nicht verwenden.

Daher ist es im Allgemeinen gefährlich - und konzeptionell falsch -, eine dynamische Zeichenfolge als einzelnes Argument zu übergeben 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

Gleiches gilt für fputsvs fprintf( fputsfügt jedoch keine neue Zeile hinzu).

leonbloy
quelle
Inwiefern wäre die Nutzung printf()weniger effizient? Zur Laufzeit? Zur Kompilierungszeit?
Franklin
10
@franklin zur Laufzeit, da die Formatzeichenfolge printfanalysiert werden muss. Dies sollte jedoch normalerweise irrelevant sein. Außerdem könnte ein cleverer Compiler dies optimieren und den printfAufruf vonputs
leonbloy am
33

Gibt neben der Formatierung putseine nichtnegative Ganzzahl zurück, wenn sie erfolgreich ist oder EOFwenn sie nicht erfolgreich ist. while printfgibt die Anzahl der gedruckten Zeichen zurück (ohne die nachfolgende Null).

Echristopherson
quelle
16

In einfachen Fällen konvertiert der Compiler Aufrufe printf()in Aufrufe anputs() .

Der folgende Code wird beispielsweise mit dem Assembler-Code kompiliert, den ich als Nächstes zeige.

#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 diesem Beispiel habe ich GCC Version 4.7.2 verwendet und die Quelle mit kompiliert gcc -o hello hello.c.

Hannu Balk
quelle
9
Und was ist mit einer neuen Linie, die Plätze in stdout setzt?
Zubergu
1
Es hätte printf("Hello world!\n");tatsächlich sein sollen, dass gcc das in Puts übersetzt. Da es sich um eine alte Nachricht handelt, werde ich sie selbst bearbeiten.
Rafael Almeida
2
Wie haben Sie den Assemblycode nach dem Kompilieren des C-Codes gelesen?
Koray Tugay
3
@ KorayTugay: die -save-tempsOption für gcc macht das
schaiba
Sie können auch ein Tool wie gdb verwenden, um eine Binärdatei zu zerlegen.
Ivan Kaloyanov
10

Richtig, printfkönnte man sich als eine mächtigere Version von vorstellen puts. printfbietet die Möglichkeit, Format Variablen für die Ausgabe mit dem Formatbezeich wie %s, %d, %lf, etc ...

Justin Ethier
quelle
10

Nach meiner Erfahrung werden printf()mehr Code eingezogen als puts()unabhängig von der Formatzeichenfolge.

Wenn ich die Formatierung nicht benötige, verwende ich sie nicht printf. Doch fwritebis stdoutarbeitet viel schneller als puts.

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

Hinweis: Gemäß Kommentaren ist '\ 0' eine Ganzzahlkonstante. Der richtige Ausdruck sollte sizeof(char)den Kommentaren entsprechen.

Thomas Matthews
quelle
2
"fwrite to stdout funktioniert viel schneller als put." - Was könnte möglicherweise der Grund sein?
Antony Hatchkins
6
@AntonyHatchkins Es ist normalerweise nicht "viel" schneller. put () muss jedoch jedes Mal einen strlen () -Aufruf für Ihren String ausführen. Wenn die Größe mit fwrite () bekannt ist, kann dies vermieden werden. Das ist so ziemlich der einzige wirkliche Beitrag zu einem Leistungsunterschied.
Wiz
8
Diese Antwort ist falsch. '\0'hat Typ int, also wird dies auf den meisten Systemen gedruckt Using fwrit. Wenn Sie 1 Byte weniger drucken möchten, verwenden sizeof (char)Sie einfach 1.
Dies
8
int puts(const char *s);

put () schreibt den String s und eine nachfolgende Newline in stdout.

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

Die Funktion printf () schreibt die Ausgabe unter der Kontrolle einer Formatzeichenfolge, die angibt, wie nachfolgende Argumente für die Ausgabe konvertiert werden, in stdout.

Ich werde diese Gelegenheit nutzen, um Sie zu bitten, die Dokumentation zu lesen.

Koray Tugay
quelle
5

Mit der Funktion printf () werden sowohl Zeichenfolgen als auch Variablen auf dem Bildschirm gedruckt, während mit der Funktion put () nur Zeichenfolgen auf Ihrem Bildschirm gedruckt werden können.

Wesley Nyandika
quelle
2

puts ist die einfache Wahl und fügt am Ende eine neue Zeile hinzu und printf schreibt die Ausgabe aus einer formatierten Zeichenfolge.

Siehe die Dokumentation für puts und fürprintf .

Ich würde empfehlen, nur zu verwenden, printfda dies konsistenter ist als die Umschaltmethode. Wenn Sie also ein Debugging durchführen, ist es weniger schmerzhaft, alle printfs als putsund zu durchsuchen printf. Meistens möchten Sie eine Variable auch in Ihren Ausdrucken ausgeben, daher putswird sie meistens im Beispielcode verwendet.

Johan Engblom
quelle
1

Beim Vergleichen puts()und printf(), obwohl ihr Speicherverbrauch fast gleich ist, puts()dauert mehr Zeit im Vergleich zu printf().

bis
quelle
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu, damit andere daraus lernen können - haben Sie zuverlässige Quellen für diese Behauptung? Oder einige Gründe, um diesen Unterschied zu erklären?
Nico Haase