Wie soll ich Typen wie off_t und size_t drucken?

148

Ich versuche Typen wie off_tund zu drucken size_t. Was ist der richtige Platzhalter dafür printf() ist tragbar ?

Oder gibt es eine ganz andere Möglichkeit, diese Variablen zu drucken?

Georg Schölly
quelle
2
@devin: Ich glaube , ich habe diese Art gefunden , während mit fopen, fseeketc. auf Mac OS X off_tist für den Offset verwendet.
Georg Schölly

Antworten:

112

Sie können zfür size_t und tfür ptrdiff_t wie in verwenden

printf("%zu %td", size, ptrdiff);

Aber meine Manpage sagt, dass einige ältere Bibliotheken einen anderen Charakter verwendet haben zund davon abraten, ihn zu verwenden. Trotzdem ist es standardisiert (nach dem C99-Standard). Für diese intmax_tund int8_tvon stdint.hund so weiter gibt es Makros, die Sie verwenden können, wie eine andere Antwort sagte:

printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);

Sie sind in der Manpage von aufgeführt inttypes.h.

Persönlich würde ich die Werte einfach auf eine andere Antwort übertragen unsigned longoder diese longempfehlen. Wenn Sie C99 verwenden, dann können Sie (und sollte natürlich) abgegeben zu unsigned long longoder long longund verwenden Sie die %lluoder %lldFormate sind.

Johannes Schaub - litb
quelle
2
off_t ist eigentlich ein signierter Long Long auf meinem System.
Georg Schölly
2
Ich denke, die Manpage rät von der Verwendung von Z (Großbuchstaben) ab, das von libc5 verwendet wurde. Es scheint z (Kleinbuchstaben) nicht zu entmutigen.
Draemon
12
Die Verwendung %zdmit a size_tist aufgrund der Nichtübereinstimmung der Vorzeichen undefiniert (C99 7.19.6.1 # 9). Es muss sein %zu.
Jens
7
Nun, wie druckt man dann off_t aus?
JohnyTex
3
@Jens Ich sehe nicht, wie %zdmit einem size_tundefinierten Verhalten aus diesem Absatz oder aus einem anderen. Tatsächlich %zerlaubt die Definition von in # 7 explizit %dmit size_tund dem entsprechenden vorzeichenbehafteten Typ, und §6.2.5 # 9 erlaubt explizit die Verwendung von Werten vorzeichenloser Typen, bei denen der entsprechende vorzeichenbehaftete Typ erwartet wird, solange der Wert ein gültiger nichtnegativer Wert ist vom signierten Typ.
Chortos-2
108

So drucken Sie off_t:

printf("%jd\n", (intmax_t)x);

So drucken Sie size_t:

printf("%zu\n", x);

So drucken Sie ssize_t:

printf("%zd\n", x);

Siehe 7.19.6.1/7 im C99-Standard oder die bequemere POSIX-Dokumentation der Formatierungscodes:

http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html

Wenn Ihre Implementierung diese Formatierungscodes nicht unterstützt (z. B. weil Sie sich auf C89 befinden), haben Sie ein kleines Problem, da AFAIK in C89 keine Ganzzahltypen mit Formatierungscodes enthält, die garantiert so groß sind wie diese Typen. Sie müssen also etwas Implementierungsspezifisches tun.

Wenn Ihr Compiler beispielsweise über long longeine Standardbibliothek verfügt und diese unterstützt %lld, können Sie davon ausgehen, dass diese anstelle von verwendet wird intmax_t. Wenn dies nicht der Fall ist, müssen Sie longauf etwas zurückgreifen , was bei einigen anderen Implementierungen fehlschlagen würde, weil es zu klein ist.

Steve Jessop
quelle
3
Dies ist bei weitem die bessere Antwort, ich hätte vergessen,% zu für unsigned size_t zu verwenden. Das Casting in intmax_t ist eine großartige Lösung für alle off_t-Funktionen auf jeder Plattform.
Peter Cordes
2
POSIX garantiert nicht, dass ssize_tes die gleiche Größe hat wie size_t, daher sollte wirklich portabler Code es in genau so konvertieren intmax_tund mit %jdgenau so drucken off_t.
Nwellnhof
off_t kann bis zu einer Größe von long long und variabel sein, abhängig von den Definitionen ... Visual Studio warnt auch davor "Warnung C4477: '_snprintf_s': Formatzeichenfolge '% jd' erfordert ein Argument vom Typ '__int64', aber variadisches Argument 1 hat den Typ 'off_t' "... Ein wirklich portabler Weg ist printf ("% lld \ n ", (long long) x);
Ericcurtin
5

Für Microsoft ist die Antwort anders. VS2013 ist weitgehend C99-kompatibel, aber "[h] die Präfixe für die Länge hh, j, z und t werden nicht unterstützt." Verwenden Sie für size_t "dh __int32 ohne Vorzeichen auf 32-Bit-Plattformen, __int64 ohne Vorzeichen auf 64-Bit-Plattformen" das Präfix I (Großbuchstabe) mit dem Typbezeichner o, u, x oder X. Siehe VS2013-Größenangabe

Off_t wird in VC \ include \ sys \ types.h als lang definiert.

NoBrassRing
quelle
Beachten Sie, wenn dies off_timmer longder Fall ist, wird es 32-Bit (selbst 64-Bit-Windows verwendet 32-Bit für long).
Sourcejedi
3

Welche Version von C verwenden Sie?

In C90 besteht die Standardpraxis darin, je nach Bedarf auf signiertes oder nicht signiertes Long zu gießen und entsprechend zu drucken. Ich habe% z für size_t gesehen, aber Harbison und Steele erwähnen es nicht unter printf (), und das würde dir auf jeden Fall bei ptrdiff_t oder was auch immer nicht helfen.

In C99 werden die verschiedenen _t-Typen mit eigenen printf-Makros geliefert. "Size is " FOO " bytes." Ich kenne also keine Details, aber das ist Teil einer ziemlich großen Include-Datei im numerischen Format.

David Thornley
quelle
3

Sie möchten die Formatierungsmakros von inttypes.h verwenden.

Siehe diese Frage: Plattformübergreifende Formatzeichenfolge für Variablen vom Typ size_t?

Michael Burr
quelle
Angenommen, off_t ist ein vorzeichenbehaftetes int in Zeigergröße (ich weiß nicht, wie die genaue Definition lautet) wie ptrdiff_t, dann würden Sie PRIdPTR oder PRIiPTR verwenden.
Michael Burr
11
Der off_tTyp ist größer als ein Zeiger auf einem 32-Bit-System, das große Dateien unterstützt (dies sind heutzutage die meisten 32-Bit-Systeme).
Dietrich Epp
1
@DietrichEpp: Eigentlich ist es schlimmer als das; Viele 32-Bit-Systeme haben sowohl off_t als auch off64_t, und abhängig von den Funktionsmakros kann off_t tatsächlich off64_t bedeuten.
SamB
1

Unter man 3 printfLinux, OS X und OpenBSD wird die Unterstützung %zfür size_tund %tfür ptrdiff_t(für C99) angezeigt, aber keine davon erwähnt off_t. Vorschläge in freier Wildbahn bieten normalerweise die %uKonvertierung für off_t, was meines Erachtens "richtig genug" ist (beide unsigned intund off_tvariieren identisch zwischen 64-Bit- und 32-Bit-Systemen).

dwc
quelle
1
Mein System (OS X) verfügt über 32-Bit unsigned intund 64-Bit off_t. Die Besetzung würde also dazu führen, dass Daten verloren gehen.
Dietrich Epp
-3

Ich habe diesen Beitrag mindestens zweimal gesehen, da die akzeptierte Antwort für mich schwer zu merken ist (ich verwende selten zoder jFlaggen und sie scheinen nicht plattformunabhängig zu sein ).

Der Standard gibt niemals klar die genaue Datenlänge von an size_t. Ich empfehle daher, zuerst die Länge size_tauf Ihrer Plattform zu überprüfen und dann eine davon auszuwählen:

if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64

Und ich schlage vor, stdintaus Gründen der Konsistenz Typen anstelle von Rohdatentypen zu verwenden.

elinx
quelle
1
Für C99 und C11 gibt der Standard ausdrücklich an, dass %zuzum Drucken von size_tWerten verwendet werden kann. Man sollte definitiv nicht auf die Verwendung eines uint32_t/ uint64_tFormat- size_tBezeichners zurückgreifen, um einen zu drucken , da es keine Garantie dafür gibt, dass diese Typen kompatibel sind.
autistische
-4

Soweit ich mich erinnere, besteht die einzige tragbare Möglichkeit darin, das Ergebnis in "unsigned long int" umzuwandeln und zu verwenden %lu.

printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
James Curran
quelle
1
Sollte "% lu" sein, da der Längenmodifikator vor der Konvertierung kommen sollte.
dwc
1
off_t ist zum Beispiel ein signiertes Long Long.
Georg Schölly
@ GeorgSchölly - Dann haben Sie ein Rätsel, weil long longes im C ++ - Standard nicht existiert und daher von Natur aus nicht portierbar ist.
James Curran
-9

benutze "% zo" für off_t. (oktal) oder "% zu" für dezimal.

Shankar
quelle
Warum sollte der Dateiversatz oktal sein?
Poolie