it-swarm.com.de

Wo finde ich die vollständige Definition des Typs off_t?

Ich sende eine Datei über 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 den Systemaufruf stat, 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 definiert in <sys/types.h>. Aber ich verstehe die Definition nicht. Es definiert nur __off_t or _off64_t sein off_t. Wo soll ich suchen __off_t? Auch ist es Konvention, dass __ wird für die meisten Dinge in Header-Dateien vorangestellt und macht mir Angst, 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 
59
FourOfAKind

Da diese Antwort immer noch positiv bewertet wird, möchte ich darauf hinweisen, dass Sie so gut wie nie in den Header-Dateien nachsehen müssen. Wenn Sie zuverlässigen Code schreiben möchten, sollten Sie sich den Standard genauer ansehen. Eine bessere Frage als "Wie ist off_t Auf meinem Computer definiert?" Ist "Wie ist off_t Durch den Standard definiert?". Das Befolgen des Standards bedeutet, dass Ihr Code heute und morgen auf jedem Computer funktioniert.

In diesem Fall wird off_t Nicht durch den C-Standard definiert. Es ist Teil des POSIX-Standards, der Sie können hier stöbern .

Leider ist off_t Nicht sehr genau definiert. Alles, was ich finden konnte, um es zu definieren, ist auf der Seite sys/types.h :

blkcnt_t Und off_t Müssen ganzzahlige Typen mit Vorzeichen sein.

Das bedeutet, dass Sie nicht sicher sind, wie groß es ist. Wenn Sie GNU C verwenden, können Sie die Anweisungen in die Antwort unten verwenden, um sicherzustellen, dass es 64 Bit sind. Oder besser, Sie können in einen definierten Standard konvertieren Größe, bevor Sie es auf die Leitung setzen. Dies ist, wie Projekte wie Google Protocol Buffers Arbeit (obwohl das ein C++ - Projekt ist).


Daher denke ich, "wo finde ich die Definition in meinen Header-Dateien" ist nicht die beste Frage. Der Vollständigkeit halber hier die Antwort:

Sie finden die Definition in bits/types.h (Wie oben in einem Kommentar angegeben, diese Datei niemals direkt einschließen), sie ist jedoch in einer Reihe von Makros ein wenig verdeckt. Eine Alternative zum Versuch, sie zu entwirren, besteht darin, die Präprozessorausgabe zu betrachten:

#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 Operator sizeof() verwenden.

Edit: Hab gerade den Teil deiner Frage zum __ Gesehen. Diese Antwort hat eine gute Diskussion . Der entscheidende Punkt ist, dass Namen, die mit __ Beginnen, für die Implementierung reserviert sind (Sie sollten also keine eigenen Definitionen mit __ Beginnen).

71
Timothy Jones

Wie es im "GNU C Library Reference Manual" heißt

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 zuverlässig die Dateigröße zwischen Client und Server darstellen möchten, können Sie:

  1. Verwenden Sie den Typ off64_t Und die Funktion stat64() entsprechend (da sie die Struktur stat64 Ausfüllt, die den Typ off64_t Selbst enthält). Typ off64_t Garantiert die gleiche Größe auf 32- und 64-Bit-Computern.
  2. Wie bereits erwähnt, kompilieren Sie Ihren Code mit -D_FILE_OFFSET_BITS == 64 Und verwenden Sie die üblichen Befehle off_t Und stat().
  3. Konvertieren Sie off_t In int64_t Mit fester Größe (C99-Standard). Anmerkung: (in meinem Buch 'C in a Nutshell' heißt es, dass es C99-Standard ist, in der Implementierung jedoch optional). 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. Die meisten Compiler (einschließlich gcc) unterstützen diese Funktion.

33
likern

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 gesamte 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;
6
chutz

Wenn Sie tragbaren Code schreiben, lautet die Antwort "Sie können es nicht sagen". Die gute Nachricht ist, dass Sie das nicht müssen. Ihr Protokoll sollte das Schreiben der Größe als (z. B.) "8 Oktetts, Big-Endian-Format" beinhalten. (Idealerweise mit einer Überprüfung, ob die tatsächliche Größe in 8 Oktetts passt.)

4
Martin Bonner