Lassen Sie uns an diesem Hallo Welt Programm einen BlickUnterschied zwischen FILE * "/ dev/stdout" und stdout
#include <stdio.h>
int main(int argc, char ** argv) {
printf("Hello, World!");
const char* sFile = "/dev/stdout"; // or /proc/self/fd/0
const char* sMode = "w";
FILE * output = fopen(sFile, sMode);
//fflush(stdout) /* forces `correct` order */
putc('!', output); // Use output or stdout from stdio.h
return 0;
}
Bei Verwendung des output
Dateideskriptors kompiliert die Ausgabe lautet:
!Hello, World!
bei der Kompilierung unter Verwendung des stdout
Dateideskriptors, der von stdio.h
bereitgestellt wird, ist die Ausgabe wie erwartet:
Hello, World!!
I erläutert, wenn dieser mit dem letzteren putc
ruft, wird es direkt um die stdout
zu drucken, und wenn die Datei-Deskriptor auf /dev/stdout
verwendet, wird es öffnet sich ein Rohr und in die drucken. Ich bin mir allerdings nicht sicher.
Das Verhalten ist noch interessanter, da es nicht das erste Zeichen des 'Hallo' überschreibt, sondern sich selbst in die erste Position des Zeilenpuffers vor der bereits gedrückten Zeichenfolge schiebt.
Aus logischer Sicht ist dies ruhig unerwartet.
Kann mir jemand erklären, was genau hier vor sich geht?
Ich cc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
und einen 3.13.0-52 Linux-Kernel w/gcc 4.8.2
bearbeiten zusammengestellt mit: I ein strace
beider Programme gemacht haben, und hier ist der wichtige Teil:
die output
(fopen ("/ dev/stdout", "w")) ohne fflush(stdout)
scenar io erzeugt:
...
open("/dev/stdout", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f62f21e9000
write(3, "!", 1!) = 1
write(1, "Hello, World!", 13Hello, World!) = 13
exit_group(0) = ?
mit fflush(stdout)
produziert und richtigen Reihenfolge erzwingt:
...
open("/dev/stdout", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
write(1, "Hello, World!", 13Hello, World!) = 13
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f5ad4557000
write(3, "!", 1!) = 1
exit_group(0) = ?
Die stdout
(aus stdlib.h) Szenario erzeugt:
...
write(1, "Hello, World!!", 14Hello, World!!) = 14
exit_group(0) = ?
So scheint es, die FILE * output = fopen("/dev/stdout")
Stream verwendet einen anderen Dateideskriptor als stdout
Auch, wie es scheint printf
verwendet stdout
So im dritten Szenario wird die Zeichenfolge zusammengebaut, bevor es auf den Strom geschoben wird.
'stdout' ist eine Datei *, kein Dateideskriptor. Ähnlich ist "Ausgabe" kein Dateideskriptor. Jeder hat einen zugrunde liegenden Dateideskriptor, und wenn Sie direkt darauf schreiben würden, würden Sie dieses Verhalten nicht sehen. (Das direkte Schreiben in den Dateideskriptor umgeht die Pufferung.) –
Der große Unterschied besteht darin, dass jede 'FILE *' einen eigenen Puffer verwendet, der nichts miteinander zu tun hat. –