Próbuję drukować typy takie jak off_t
i size_t
. Jaki jest prawidłowy symbol zastępczy dla printf()
tego, że jest przenośny ?
A może jest zupełnie inny sposób drukowania tych zmiennych?
Próbuję drukować typy takie jak off_t
i size_t
. Jaki jest prawidłowy symbol zastępczy dla printf()
tego, że jest przenośny ?
A może jest zupełnie inny sposób drukowania tych zmiennych?
Odpowiedzi:
Możesz użyć z
dla size_t i t
dla ptrdiff_t jak w
printf("%zu %td", size, ptrdiff);
Ale moja strona podręcznika mówi, że jakaś starsza biblioteka używała innego znaku niż z
i zniechęca do jego używania. Niemniej jednak jest znormalizowany (według standardu C99). Dla tych intmax_t
i int8_t
od stdint.h
i tak dalej, są makra można użyć, jak inna odpowiedź powiedział:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Są one wymienione na stronie podręcznika inttypes.h
.
Osobiście chciałbym po prostu przypisać wartości unsigned long
lub long
polubić inne zalecenia. Jeśli korzystasz z C99, następnie można (a nawet powinien, oczywiście) oddanych do unsigned long long
lub long long
i użyj %llu
lub %lld
formatów odpowiednio.
%zd
z a size_t
jest niezdefiniowanym zachowaniem z powodu niezgodności podpisów (C99 7.19.6.1 # 9). To musi być %zu
.
%zd
pomocą a size_t
uzyskuje się niezdefiniowane zachowanie z tego akapitu lub innego. W rzeczywistości, definicja %z
w 7 wyraźnie zezwala %d
się size_t
i podpisał odpowiedni typ i §6.2.5 # 9 wyraźnie pozwala na stosowanie wartości niepodpisanych typów gdzie spodziewane jest odpowiedni typ podpisana, dopóki wartość jest prawidłową wartością dodatnią podpisanego typu.
Aby wydrukować off_t
:
printf("%jd\n", (intmax_t)x);
Aby wydrukować size_t
:
printf("%zu\n", x);
Aby wydrukować ssize_t
:
printf("%zd\n", x);
Zobacz 7.19.6.1/7 w standardzie C99 lub wygodniejszą dokumentację POSIX dotyczącą kodów formatowania:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Jeśli twoja implementacja nie obsługuje tych kodów formatujących (na przykład ponieważ jesteś na C89), masz mały problem, ponieważ AFAIK nie ma typów całkowitych w C89, które mają kody formatujące i gwarantują, że są tak duże jak te typy. Musisz więc zrobić coś specyficznego dla implementacji.
Na przykład, jeśli Twój kompilator ma long long
i obsługuje standardową bibliotekę %lld
, możesz śmiało oczekiwać, że będzie to służyć zamiast intmax_t
. Ale jeśli tak się nie stanie, będziesz musiał wrócić do long
, co w przypadku niektórych innych implementacji nie powiedzie się, ponieważ jest za małe.
ssize_t
ma taki sam rozmiar jak size_t
, więc prawdziwie przenośny kod powinien go konwertować intmax_t
i drukować z %jd
takim samym off_t
.
W przypadku firmy Microsoft odpowiedź jest inna. VS2013 jest w dużej mierze zgodny z C99, ale „[t] he hh, j, z i t prefiksy długości nie są obsługiwane”. Dla size_t "to znaczy unsigned __int32 na platformach 32-bitowych, unsigned __int64 na platformach 64-bitowych" użyj przedrostka I (wielkie oko) ze specyfikatorem typu o, u, x lub X. Zobacz specyfikację rozmiaru VS2013
Jeśli chodzi o off_t, jest zdefiniowany jako długi w VC \ include \ sys \ types.h.
off_t
zawsze jest long
to 32-bitowe (nawet 64-bitowy system Windows używa 32-bitowego long
).
Której wersji C używasz?
W C90 standardową praktyką jest rzutowanie odpowiednio do długości ze znakiem lub bez znaku i odpowiednie drukowanie. Widziałem% z dla size_t, ale Harbison i Steele nie wspominają o tym w printf (), aw każdym razie to nie pomoże ci z ptrdiff_t lub czymkolwiek.
W C99 różne typy _t mają własne makra printf, więc coś w rodzaju "Size is " FOO " bytes."
nie znam szczegółów, ale jest to część dość dużego pliku dołączanego formatu liczbowego.
Będziesz chciał użyć makr formatujących z inttypes.h.
Zobacz to pytanie: Ciąg formatu międzyplatformowego dla zmiennych typu size_t?
off_t
Typ jest większy niż wskaźnik w dowolnym systemie 32-bitowym, który obsługuje duże pliki (co jest większość 32-bitowe systemy te dni).
Patrząc man 3 printf
na Linuksa, OS X i OpenBSD, wszystkie pokazują wsparcie %z
dla size_t
i %t
dla ptrdiff_t
(dla C99), ale żadne z nich nie wspomina off_t
. Sugestie w środowisku naturalnym zazwyczaj oferują %u
konwersję off_t
, która jest „wystarczająco poprawna”, o ile wiem (oba unsigned int
i off_t
różnią się identycznie między systemami 64-bitowymi i 32-bitowymi).
unsigned int
i 64-bitowy off_t
. Więc obsada spowodowałaby utratę danych.
Widziałem ten post co najmniej dwa razy, ponieważ zaakceptowaną odpowiedź trudno mi zapamiętać (rzadko używam z
lub j
flag i wydaje się, że nie są niezależne od platformy ).
Norma nie mówi wyraźnie dokładna długość danych size_t
, więc proponuję najpierw należy sprawdzić długość size_t
od platformy, a następnie wybrać jedną z nich:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
I sugeruję używanie stdint
typów zamiast surowych typów danych w celu zachowania spójności.
%zu
których można użyć do wydrukowania size_t
wartości. Trzeba na pewno nie uciekać się do korzystania z uint32_t
/ uint64_t
formatu specyfikatora aby wydrukować size_t
, ponieważ nie ma gwarancji, że te typy są kompatybilne.
Jak sobie przypominam, jedynym przenośnym sposobem na zrobienie tego jest rzutowanie wyniku na „unsigned long int” i użycie %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
nie istnieje w standardzie C ++, a zatem jest z natury nieprzenośny.
fopen
,fseek
itp na Mac OS X.off_t
służy do przesunięcia.