Waar vind je de volledige definitie van off_t type?

Ik verzend een bestand van client naar server via TCP. Om het einde van het bestand te markeren, stuur ik graag de bestandsgrootte vóór de daadwerkelijke gegevens. Dus ik gebruik statsysteemaanroep om de grootte van het bestand te vinden. Dit is van het type off_t. Ik wil graag weten hoeveel bytes het in beslag neemt, zodat ik het aan de serverzijde goed kan lezen. Het wordt gedefinieerd in de <sys/types.h>. Maar ik begrijp de definitie niet. Het definieert gewoon __off_t or _off64_tals off_t. Waar moet je zoeken naar __off_t? Het is ook een conventie dat __het voorvoegsel is voor de meeste dingen in header-bestanden en maakt me bang als ik header-bestanden lees om het beter te begrijpen. Hoe lees je een headerbestand beter?

#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 

Antwoord 1, autoriteit 100%

Aangezien dit antwoord nog steeds wordt gestemd, wil ik erop wijzen dat je bijna nooit in de header-bestanden hoeft te kijken. Als je betrouwbare code wilt schrijven, kun je veel beter in de standaard kijken. Dus het antwoord op “waar kan ik de volledige definitie van off_tvinden” is “in een standaard, in plaats van een header-bestand”. Het volgen van de norm betekent dat uw code vandaag en morgen werkt, op elke machine.

In dit geval wordt off_tniet gedefinieerd door de C-standaard. Het maakt deel uit van de POSIX-standaard, die u hier kunt bekijken.

Helaas is off_tniet erg strikt gedefinieerd. Alles wat ik kon vinden om het te definiëren is op de pagina op sys/types.h:

blkcnt_ten off_tmoeten ondertekende integer-types zijn.

Dit betekent dat je niet zeker weet hoe groot het is. Als je GNU C gebruikt, kun je de instructies in het onderstaande antwoordgebruiken om ervoor te zorgen dat het 64 bits is. Of beter nog, u kunt converteren naar een standaard gedefinieerde maat voordat u deze op de draad plaatst. Dit is hoe projecten zoals Google’s Protocol Bufferswerken (hoewel dat een C++-project is).


Voor de volledigheid is hier het antwoord op “welk headerbestand definieert off_t?”:

Op mijn computer (en de meeste machines die glibc gebruiken) vind je de definitie in bits/types.h(zoals een opmerking bovenaan zegt, voeg dit bestand nooit rechtstreeks toe), maar het is een beetje verduisterd in een aantal macro’s. Een alternatief voor proberen ze te ontrafelen is om naar de preprocessor-uitvoer te kijken:

#include <stdio.h>
#include <sys/types.h>
int main(void) {
  off_t blah;
  return 0;
}

En dan:

$ gcc -E sizes.c  | grep __off_t
typedef long int __off_t;
....

Als u echter de grootte van iets wilt weten, kunt u altijd de operator sizeof()gebruiken.

Bewerken: ik zag net het deel van je vraag over de __. Dit antwoord heeft een goede discussie. Het belangrijkste punt is dat namen die beginnen met __gereserveerd zijn voor de implementatie (je moet dus niet je eigen definities beginnen met __).


Antwoord 2, autoriteit 45%

Zoals de “GNU C Library Reference Manual” zegt

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.

en

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.

Als u dus een betrouwbare manier wilt om de bestandsgrootte tussen client en server weer te geven, kunt u:

  1. Gebruik het type off64_ten de functie stat64()dienovereenkomstig (omdat het de structuur stat64vult, die off64_tbevat zelf typen). Typ off64_tgarandeert dezelfde grootte op 32- en 64-bits machines.
  2. Zoals eerder vermeld, compileer uw codemet -D_FILE_OFFSET_BITS == 64en gebruik de gebruikelijke off_ten stat().
  3. Converteer off_tnaar int64_tmet vaste grootte (C99-standaard).
    Opmerking: (Mijn boek ‘C in een notendop’ zegt dat het C99-standaard is, maar optioneel in implementatie). De nieuwste C11-standaard zegt:
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.

en over implementatie:

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.

Aldus kan de C-standaard in het algemeen geen typen met vaste formaten garanderen. Maar de meeste compilers (inclusief GCC) ondersteunen deze functie.


Antwoord 3, Autoriteit 9%

Als u problemen ondervindt bij het traceren van de definities, kunt u de voorverwerkte uitvoer van de compiler gebruiken die u alles zal vertellen wat u moet weten. B.g

$ 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) ;

Als u naar de volledige uitvoer kijkt, kunt u zelfs de exacte koptekst-bestandslocatie en het lijnnummer zien waar deze is gedefinieerd:

# 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;

Antwoord 4, autoriteit 6%

Als je draagbare code schrijft, is het antwoord “je weet het niet”, het goede nieuws is dat je dat niet hoeft te doen. Uw protocol moet inhouden dat de grootte wordt geschreven als (bijv.) “8 octetten, big-endian-formaat” (Ideaal met een controle dat de werkelijke grootte in 8 octetten past.)

Other episodes