Wo finde ich die vollständige Definition des Typs off_t?
Lesezeit: 7 Minuten
Vier von einer Sorte
Ich sende Dateien vom Client zum Server über TCP. Um das Ende der Datei zu markieren, sende ich gerne die Dateigröße vor den eigentlichen Daten. Also benutze ich 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 sein off_t. Wo suchen __off_t? Auch das ist Konvention __ ist den meisten Dingen in Header-Dateien vorangestellt und macht mir Angst, wenn ich Header-Dateien lese, um sie besser zu verstehen. Wie liest man eine Header-Datei besser?
Alles, was mit beginnt __ ist für die Verwendung durch die Implementierung reserviert (es sei denn, der Standard definiert eine Bedeutung dafür, wie in __func__ oder __FILE__). Die Indirektionsebene lässt die Implementierung ihren eigenen Typ definieren __off_t ohne sich in etwas einzumischen, was Sie rechtmäßig tun können. Die plattformspezifischen Bits der Header können dann besser ausgeblendet werden (damit eine einzelne Kopie des Quellcodes beispielsweise 32-Bit- und 64-Bit-Kompilierungen auf einer einzelnen Maschine verarbeiten kann). Das Lesen von Standardüberschriften ist eine große Aufgabe, da es so viele miteinander verknüpfte Definitionen gibt.
– Jonathan Leffler
31. Januar 2012 um 3:04 Uhr
Timothy Jones
Da diese Antwort immer noch gewählt wird, möchte ich darauf hinweisen, dass Sie fast nie in die Header-Dateien schauen müssen. Wer zuverlässigen Code schreiben will, ist mit einem Blick in den Standard viel besser bedient. Die Antwort auf “Wo finde ich die vollständige Definition von off_t” befindet sich “in einem Standard und nicht in einer Header-Datei”. Dem Standard zu folgen 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, der hier kannst du stöbern.
Leider, off_t ist nicht sehr streng definiert. Alles, was ich finden konnte, um es zu definieren, ist auf der Seite auf sys/types.h:
blkcnt_t und off_t müssen vorzeichenbehaftete Integer-Typen sein.
Das bedeutet, dass Sie nicht sicher sein können, wie groß es ist. Wenn Sie GNU C verwenden, können Sie die Anweisungen in der folgenden Antwort verwenden, um sicherzustellen, dass es sich um 64 Bit handelt. Oder besser, Sie können es in eine standardisierte Größe umwandeln, bevor Sie es auf den Draht legen. So funktionieren Projekte wie das von Google Protokollpuffer funktionieren (obwohl das ein C++-Projekt ist).
Der Vollständigkeit halber hier die Antwort auf “welche Header-Datei definiert off_t?”:
Auf meinem Computer (und den meisten Computern, die glibc verwenden) finden Sie die Definition in bits/types.h (Wie ein Kommentar oben sagt, fügen Sie diese Datei niemals direkt ein), aber sie ist in einer Reihe von Makros etwas verdeckt. Eine Alternative zum Versuch, sie zu enträtseln, besteht darin, sich die Ausgabe des Präprozessors anzusehen:
$ 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 die verwenden sizeof() Operator.
Bearbeiten: Ich habe gerade den Teil Ihrer Frage zu dem gesehen __. Diese Antwort hat eine gute Diskussion. Der entscheidende Punkt ist, dass Namen mit beginnen __ sind für die Implementierung reserviert (Sie sollten Ihre eigenen Definitionen also nicht mit beginnen __).
Ich verwende die Größe von on off_t. Auf meinem Rechner (Client) sind es 4 Bytes. Die maximale Dateigröße, die ich darstellen kann, beträgt also 2 ^ 32 Bytes. Muss das in diesem speziellen Fall mit der Größe von off_t auf meinem Server übereinstimmen? Das sollte ich nicht glauben.
– Vier von einer Sorte
31. Januar 2012 um 2:54 Uhr
Es ist wahr, dass off_t können auf verschiedenen Maschinen (oder Compilern) unterschiedliche Größen haben. Beachten Sie, dass Sie in GCC verwenden können -D_FILE_OFFSET_BITS=64 8 Byte bekommen off_t und size_t Definitionen.
– Timothy Jones
31. Januar 2012 um 2:57 Uhr
Ok. Also, was sollte der Server nach den ersten 4 oder den ersten 8 Bytes suchen, um die Länge der Datei zu erhalten?
– Vier von einer Sorte
31. Januar 2012 um 2:59 Uhr
OK ich habe es. Ich sollte einen größeren Wert wie long long verwenden, der garantiert auf beiden Computern gleich ist, und dann auf ihn übertragen wird, um ihn an den Server zu senden.
– Vier von einer Sorte
31. Januar 2012 um 3:04 Uhr
Es ist nicht garantiert, dass lang lang auf zwei Maschinen die gleiche Größe hat – die genaue Größe ist nicht standardisiert.
– Timothy Jones
31. Januar 2012 um 3:06 Uhr
mögen
Wie das “GNU C Library Reference Manual” sagt
off_t
This is a signed integer type used to represent file sizes.
In the GNU C Library, this type is no narrower than int.
If the source is compiled with _FILE_OFFSET_BITS == 64 this
type is transparently replaced by off64_t.
und
off64_t
This type is used similar to off_t. The difference is that
even on 32 bit machines, where the off_t type would have 32 bits,
off64_t has 64 bits and so is able to address files up to 2^63 bytes
in length. When compiling with _FILE_OFFSET_BITS == 64 this type
is available under the name off_t.
Wenn Sie also eine zuverlässige Darstellung der Dateigröße zwischen Client und Server wünschen, können Sie:
Verwenden off64_t Typ und stat64() Funktion entsprechend (wie es die Struktur füllt stat64was beinhaltet off64_t selbst eingeben). Typ off64_t garantiert die gleiche Größe auf 32- und 64-Bit-Rechnern.
Wie bereits erwähnt, kompilieren dein Code mit -D_FILE_OFFSET_BITS == 64 und normal verwenden off_t und stat().
Konvertieren off_t tippen int64_t mit fester Größe (C99-Standard). Notiz: (mein Buch ‘C auf den Punkt gebracht’ sagt, dass es C99-Standard ist, aber optional in der Implementierung). Der neueste C11-Standard sagt:
7.20.1.1 Exact-width integer types
1 The typedef name intN_t designates a signed integer type with width N ,
no padding bits, and a two’s complement representation. Thus, int8_t
denotes such a signed integer type with a width of exactly 8 bits.
without mentioning.
Und zur Umsetzung:
7.20 Integer types <stdint.h>
... An implementation shall provide those types described as ‘‘required’’,
but need not provide any of the others (described as ‘‘optional’’).
...
The following types are required:
int_least8_t uint_least8_t
int_least16_t uint_least16_t
int_least32_t uint_least32_t
int_least64_t uint_least64_t
All other types of this form are optional.
Daher kann der C-Standard im Allgemeinen keine Typen mit festen Größen garantieren. Aber die meisten Compiler (einschließlich gcc) unterstützen diese Funktion.
“Dies ist ein vorzeichenbehafteter Integer-Typ, der zur Darstellung von Dateigrößen verwendet wird”. Wenn sie die Größe von Dateien darstellen, warum dann „signiert“ verwenden?
– Rodrigo
20. April 2021 um 7:07 Uhr
(1) Weil es praktisch ist, negative Werte zurückzugeben, um Fehler anzuzeigen. (2) Weil der Satz sagen sollte: “Dies ist ein vorzeichenbehafteter Integer-Typ, der verwendet wird, um Datei-Offsets darzustellen”, dh vorwärts oder rückwärts suchen.
– William Cushing
26. Mai 2021 um 1:26 Uhr
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;
Wenn Sie portablen Code schreiben, lautet die Antwort “Sie können es nicht sagen”, die gute Nachricht ist, dass Sie es nicht müssen. Ihr Protokoll sollte das Schreiben der Größe als (z. B.) “8 Oktette, Big-Endian-Format” beinhalten (idealerweise mit einer Überprüfung, ob die tatsächliche Größe in 8 Oktette passt.)
14198500cookie-checkWo finde ich die vollständige Definition des Typs off_t?yes
Alles, was mit beginnt
__
ist für die Verwendung durch die Implementierung reserviert (es sei denn, der Standard definiert eine Bedeutung dafür, wie in__func__
oder__FILE__
). Die Indirektionsebene lässt die Implementierung ihren eigenen Typ definieren__off_t
ohne sich in etwas einzumischen, was Sie rechtmäßig tun können. Die plattformspezifischen Bits der Header können dann besser ausgeblendet werden (damit eine einzelne Kopie des Quellcodes beispielsweise 32-Bit- und 64-Bit-Kompilierungen auf einer einzelnen Maschine verarbeiten kann). Das Lesen von Standardüberschriften ist eine große Aufgabe, da es so viele miteinander verknüpfte Definitionen gibt.– Jonathan Leffler
31. Januar 2012 um 3:04 Uhr