So ziemlich.
Wenn Sie die Standardausgabe des Programms auf /dev/null
umleiten , jeder Aufruf von printf(3)
wertet weiterhin alle Argumente aus, und der Zeichenfolgenformatierungsprozess findet weiterhin statt, bevor write(2)
aufgerufen wird , wodurch die vollständig formatierte Zeichenfolge in die Standardausgabe des Prozesses geschrieben wird. Auf der Kernel-Ebene werden die Daten nicht auf die Festplatte geschrieben, sondern vom Handler verworfen, der dem speziellen Gerät /dev/null
zugeordnet ist .
Im besten Fall umgehen oder vermeiden Sie also den Overhead, die Argumente auszuwerten und an printf
zu übergeben , der Zeichenfolgenformatierungsjob hinter printf
, und mindestens einen Systemaufruf, um die Daten tatsächlich zu schreiben, indem stdout einfach auf /dev/null
umgeleitet wird . Nun, das ist ein echter Unterschied zu Linux. Die Implementierung gibt nur die Anzahl der Bytes zurück, die Sie schreiben wollten (angegeben durch das dritte Argument Ihres Aufrufs von write(2)
) und ignoriert alles andere (siehe diese Antwort). Abhängig von der zu schreibenden Datenmenge und der Geschwindigkeit des Zielgeräts (Festplatte oder Terminal) kann der Leistungsunterschied stark variieren. Auf eingebetteten Systemen wird im Allgemeinen das Schreiben auf die Festplatte unterbrochen, indem auf /dev/null
umgeleitet wird kann einige Systemressourcen für eine nicht triviale Menge an geschriebenen Daten einsparen.
Obwohl das Programm theoretisch /dev/null
erkennen könnte und einige Optimierungen innerhalb der Einschränkungen der Standards durchführen, denen sie entsprechen (ISO C und POSIX), basierend auf dem allgemeinen Verständnis gängiger Implementierungen, tun sie dies praktisch nicht (dh mir ist kein Unix- oder Linux-System bekannt, das dies tut).
Der POSIX-Standard verlangt, dass bei jedem Aufruf von printf(3)
in die Standardausgabe geschrieben wird , daher ist es nicht standardkonform, den Aufruf von write(2)
zu unterdrücken abhängig von den zugehörigen Dateideskriptoren. Weitere Einzelheiten zu den POSIX-Anforderungen finden Sie in Damons Antwort. Oh, und eine kurze Anmerkung:Alle Linux-Distributionen sind praktisch POSIX-konform, obwohl sie nicht zertifiziert sind so sein.
Beachten Sie das, wenn Sie printf
ersetzen vollständig, einige Nebenwirkungen können schief gehen, zum Beispiel printf("%d%n", a++, &b)
. Wenn Sie die Ausgabe abhängig von der Programmausführungsumgebung wirklich unterdrücken müssen, ziehen Sie in Betracht, ein globales Flag zu setzen und printf zu beenden, um das Flag vor dem Drucken zu überprüfen – es wird das Programm nicht in einem Ausmaß verlangsamen, in dem der Leistungsverlust sichtbar ist , da eine einzelne Bedingungsprüfung viel ist schneller als printf
anzurufen und die gesamte Zeichenfolgenformatierung durchführen.
Die printf
Funktion wird schreiben Sie an stdout
. Es entspricht nicht der Optimierung für /dev/null
.Daher haben Sie den Aufwand, den Formatstring zu parsen und alle notwendigen Argumente auszuwerten, und Sie haben mindestens einen Systemaufruf, außerdem kopieren Sie einen Puffer in den Kernel-Adressraum (was im Vergleich zu den Kosten des Systemaufrufs vernachlässigbar ist). ).
Diese Antwort basiert auf der spezifischen Dokumentation von POSIX.
Systemschnittstellen
dprintf, fprintf, printf, snprintf, sprintf - formatierte Ausgabe drucken
Die Funktion fprintf() soll die Ausgabe auf dem benannten Ausgabestrom platzieren. Die Funktion printf() soll die Ausgabe auf dem Standardausgabestrom stdout platzieren. Die sprintf()-Funktion platziert die Ausgabe gefolgt vom Null-Byte, '\0', in aufeinanderfolgenden Bytes, beginnend bei *s; Es liegt in der Verantwortung des Benutzers sicherzustellen, dass genügend Speicherplatz vorhanden ist.
Basisdefinitionen
soll
Beschreibt für eine Implementierung, die POSIX.1-2017 entspricht, eine Funktion oder ein Verhalten, das obligatorisch ist. Eine Anwendung kann sich auf die Existenz der Funktion oder des Verhaltens verlassen.