Ich sende eine Datei mit TCP vom Client zum Server. Um das Ende der Datei zu markieren, sende ich gerne die Dateigröße vor den eigentlichen Daten. Also benutze ich einen stat
Systemaufruf, um die Größe der Datei zu ermitteln. Dies ist vom Typ off_t
. Ich möchte wissen, wie viele Bytes es belegt, damit ich es auf der Serverseite richtig lesen kann. Es ist in der definiert <sys/types.h>
. Aber ich verstehe die Definition nicht. Es definiert nur __off_t or _off64_t
zu sein off_t
. Wo suchen __off_t
? Es ist auch eine Konvention, die __
für die meisten Dinge in Header-Dateien vorangestellt ist und mir Angst macht, wenn ich Header-Dateien lese, um sie besser zu verstehen. Wie kann man eine Header-Datei besser lesen?
#ifndef __off_t_defined
# ifndef __USE_FILE_OFFSET64
typedef __off_t off_t;
# else
typedef __off64_t off_t;
# endif
# define __off_t_defined
#endif
c
sockets
networking
types
header-files
Vier von einer Sorte
quelle
quelle
__
ist für die Verwendung durch die Implementierung reserviert (es sei denn, der Standard definiert eine Bedeutung dafür, wie in__func__
oder__FILE__
). Durch die Indirektionsebene kann die Implementierung ihren eigenen Typ definieren,__off_t
ohne dass Sie irgendetwas stören, was Sie rechtmäßig tun können. Die plattformspezifischen Bits der Header können dann besser ausgeblendet werden (sodass eine einzelne Kopie des Quellcodes beispielsweise 32-Bit- und 64-Bit-Kompilierungen auf einem einzelnen Computer verarbeiten kann). Das Lesen von Standardheadern ist eine große Aufgabe, da es so viele miteinander verknüpfte Definitionen gibt.Antworten:
Da diese Antwort immer noch abgestimmt wird, möchte ich darauf hinweisen, dass Sie fast nie in den Header-Dateien suchen müssen. Wenn Sie zuverlässigen Code schreiben möchten, ist es viel besser, wenn Sie sich den Standard ansehen. Eine bessere Frage als "Wie ist
off_t
auf meinem Computeroff_t
definiert?" Ist "Wie wird durch den Standard definiert?". Das Befolgen des Standards bedeutet, dass Ihr Code heute und morgen auf jedem Computer funktioniert.In diesem Fall
off_t
ist nicht durch den C-Standard definiert. Es ist Teil des POSIX-Standards, den Sie hier durchsuchen können .Ist leider
off_t
nicht sehr streng definiert. Alles, was ich finden konnte, um es zu definieren, ist auf der Seite übersys/types.h
:Dies bedeutet, dass Sie nicht sicher sein können, wie groß es ist. Wenn Sie GNU C verwenden, können Sie anhand der Anweisungen in der folgenden Antwort sicherstellen, dass es sich um 64 Bit handelt. Oder besser, Sie können in eine Standardgröße konvertieren, bevor Sie sie auf den Draht legen. So funktionieren Projekte wie die Protokollpuffer von Google (obwohl dies ein C ++ - Projekt ist).
Daher denke ich, dass "Wo finde ich die Definition in meinen Header-Dateien?" Nicht die beste Frage ist. Der Vollständigkeit halber hier die Antwort:
Auf meinem Computer (und den meisten Computern, die glibc verwenden) finden Sie die Definition in
bits/types.h
(wie ein Kommentar oben sagt, schließen Sie diese Datei niemals direkt ein), aber sie ist in einer Reihe von Makros etwas verdeckt. Eine Alternative zu dem Versuch, sie zu entwirren, besteht darin, sich die Präprozessorausgabe anzusehen:#include <stdio.h> #include <sys/types.h> int main(void) { off_t blah; return 0; }
Und dann:
$ gcc -E sizes.c | grep __off_t typedef long int __off_t; ....
Wenn Sie jedoch die Größe von etwas wissen möchten, können Sie immer den
sizeof()
Operator verwenden.Edit: Hab gerade den Teil deiner Frage über die gesehen
__
. Diese Antwort hat eine gute Diskussion . Der entscheidende Punkt ist, dass Namen, die mit beginnen__
, für die Implementierung reserviert sind (daher sollten Sie Ihre eigenen Definitionen nicht mit beginnen__
).quelle
off_t
es auf verschiedenen Maschinen (oder Compilern) unterschiedliche Größen geben kann. Beachten Sie, dass Sie in GCC-D_FILE_OFFSET_BITS=64
8 Byteoff_t
undsize_t
Definitionen abrufen können .Wie das "GNU C Library Reference Manual" sagt
und
Wenn Sie also eine zuverlässige Darstellung der Dateigröße zwischen Client und Server wünschen, können Sie:
off64_t
Typ undstat64()
Funktion entsprechend (da sie die Struktur ausfülltstat64
, die denoff64_t
Typ selbst enthält ). Geben Sieoff64_t
garantiert die gleiche Größe auf 32 und 64 - Bit - Maschinen.-D_FILE_OFFSET_BITS == 64
und verwenden Sie das üblicheoff_t
undstat()
.off_t
Typint64_t
mit fester Größe konvertieren (C99-Standard). Hinweis: (Mein Buch 'C in a Nutshell' besagt, dass es C99-Standard ist, aber in der Implementierung optional). Der neueste C11-Standard lautet:Und zur Umsetzung:
Daher kann der C-Standard im Allgemeinen keine Typen mit festen Größen garantieren. Die meisten Compiler (einschließlich gcc) unterstützen diese Funktion.
quelle
Wenn Sie Probleme haben, die Definitionen zu verfolgen, können Sie die vorverarbeitete Ausgabe des Compilers verwenden, die Ihnen alles sagt, was Sie wissen müssen. Z.B
$ cat test.c #include <stdio.h> $ cc -E test.c | grep off_t typedef long int __off_t; typedef __off64_t __loff_t; __off_t __pos; __off_t _old_offset; typedef __off_t off_t; extern int fseeko (FILE *__stream, __off_t __off, int __whence); extern __off_t ftello (FILE *__stream) ;
Wenn Sie sich die vollständige Ausgabe ansehen, können Sie sogar den genauen Speicherort der Header-Datei und die Zeilennummer sehen, in der sie definiert wurde:
# 132 "/usr/include/bits/types.h" 2 3 4 typedef unsigned long int __dev_t; typedef unsigned int __uid_t; typedef unsigned int __gid_t; typedef unsigned long int __ino_t; typedef unsigned long int __ino64_t; typedef unsigned int __mode_t; typedef unsigned long int __nlink_t; typedef long int __off_t; typedef long int __off64_t;
...
# 91 "/usr/include/stdio.h" 3 4 typedef __off_t off_t;
quelle
Wenn Sie tragbaren Code schreiben, lautet die Antwort "Sie können es nicht sagen". Die gute Nachricht ist, dass Sie dies nicht müssen. Ihr Protokoll sollte das Schreiben der Größe als (z. B.) "8 Oktette, Big-Endian-Format" beinhalten (idealerweise mit der Überprüfung, ob die tatsächliche Größe in 8 Oktette passt.)
quelle