printf specyfikatory formatu dla uint32_t i size_t

101

Mam następujące

size_t   i = 0;
uint32_t k = 0;

printf("i [ %lu ] k [ %u ]\n", i, k);

Podczas kompilacji pojawia się następujące ostrzeżenie:

format ‘%lu expects type long unsigned int’, but argument has type uint32_t

Kiedy przeprowadziłem to za pomocą szyny, otrzymałem:

Format argument 1 to printf (%u) expects unsigned int gets size_t: k

Wielkie dzięki za wszelkie rady,

ant2009
źródło
2
C89 nie obsługuje uint32_tz <stdint.h>lub <inttypes.h>; jeśli chcesz używać tych typów, powinieneś uaktualnić do C89. Jako rozszerzenie jest prawdopodobne, że GCC pozwala na ich użycie, ale C89 nie miał takiej obsługi.
Jonathan Leffler
11
Oficjalnym modyfikatorem formatu C99 size_tjest „z”, jak w "%zu".
Jonathan Leffler
1
stackoverflow.com/questions/1401526/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Uważam, że odpowiedź @ kenny jest najlepsza uint32_t, ale jej brakuje size_t. Odpowiedź @ u0b34a0f6ae obejmuje oba.
jww
Druga wzmianka o C89 w pierwszym komentarzu Jonathana Lefflera powinna być C99
bph

Odpowiedzi:

28

Wygląda na to, że spodziewasz size_tsię tego samego unsigned long(prawdopodobnie 64 bity), gdy w rzeczywistości jest to unsigned int(32 bity). Spróbuj użyć %zuw obu przypadkach.

Nie jestem jednak do końca pewien.

Tryb
źródło
1
Brak ostrzeżeń podczas kompilacji. Jednak po uruchomieniu splint otrzymuję następujące informacje: 1) printf (% u) oczekuje, że unsigned int pobiera uint32_t: i 2) printf (% u) spodziewa się unsigned int pobiera size_t: k
ant2009
Wygląda więc na to, że szyna jest po prostu pedantyczna. Prawdopodobnie wychodzi z nazw typów w kodzie źródłowym i nie zdaje sobie sprawy, że są one równoważne. Zastanawiam się, co by to zrobiło z odpowiedzią @ KennyTM… Z pewnością powinno być bardziej przenośne.
Koło zębate
3
szyna faktycznie robi właściwą rzecz. To, że int32_ttak się składa, że ​​znajduje się intna twoim kompilatorze / platformie, nie oznacza, że ​​może nie być longna innym. To samo dotyczy size_t. W rzeczywistości wychodzi z drogi i wykonuje więcej pracy, aby wykryć ten błąd przenośności, ponieważ prostym, naturalnym sprawdzeniem byłoby po prostu honorowanie typedef, tak jak robi to kompilator.
R .. GitHub PRZESTAŃ POMÓC NA LODZIE
4
-1, przepraszam, to nie jest przenośne. Potrzebne jest tylko to, aby specyfikatory formatu i typy były zgodne, i zawsze możesz rzutować, aby to było prawdą. long ma co najmniej 32 bity, więc %lurazem z (unsigned long)kjest zawsze poprawne. size_tjest trudniejszy, dlatego %zuzostał dodany w C99. Jeśli nie możesz tego użyć, potraktuj to tak samo k( longjest największym typem w C89, size_tjest mało prawdopodobne, aby był większy).
u0b34a0f6ae
140

Próbować

#include <inttypes.h>
...

printf("i [ %zu ] k [ %"PRIu32" ]\n", i, k);

Symbol zreprezentuje liczbę całkowitą o takiej samej długości jak size_t, a PRIu32makro zdefiniowane w nagłówku C99inttypes.h reprezentuje 32-bitową liczbę całkowitą bez znaku.

kennytm
źródło
3
@robUK: Heh. Proponuję zgłosić błąd dotyczący szyny.
kennytm
8
To jest właściwa odpowiedź. Chociaż moja osobista rekomendacja to po prostu rzucać np printf( "%lu", (unsigned long )i ). W przeciwnym razie kończy się później stosem ostrzeżeń w całym kodzie z powodu zmiany typu.
Dummy00001
1
To jest poprawna odpowiedź. Zgadzam się z KennymTM w sprawie zgłoszenia błędu dotyczącego szyny. Nawiasem mówiąc, „% zu” to właściwy format dla size_t. Nie potrzebujesz żadnych makr PRI * do drukowania size_t.
R .. GitHub PRZESTAŃ POMÓC NA LODZIE
1
O ile dobrze pamiętam,% zu to C99, aw pytaniu napisał „C89”.
alcor
8
@alcor tak, umieścił C89 (najwyraźniej flagę kompilatora gcc, którego używa), ale używa, uint32_twięc w rzeczywistości jest to kod C99 i powinien być skompilowany jako taki.
Colin D Bennett
28

Potrzebne jest tylko to, aby specyfikatory formatu i typy były zgodne i zawsze możesz rzutować, aby to było prawdą. longma co najmniej 32 bity, więc %lurazem z (unsigned long)kjest zawsze poprawne:

uint32_t k;
printf("%lu\n", (unsigned long)k);

size_tjest trudniejszy, dlatego %zuzostał dodany w C99. Jeśli nie możesz tego użyć, potraktuj to tak samo k( longjest największym typem w C89, size_tjest mało prawdopodobne, aby był większy).

size_t sz;
printf("%zu\n", sz);  /* C99 version */
printf("%lu\n", (unsigned long)sz);  /* common C89 version */

Jeśli specyfikatory formatu nie są prawidłowe dla typu, który przekazujesz, printfspowoduje to odczytanie zbyt dużej lub zbyt małej ilości pamięci z tablicy. Tak długo, jak używasz wyraźnych rzutów, aby dopasować typy, jest przenośny.

u0b34a0f6ae
źródło
17

Jeśli nie chcesz używać makr PRI *, innym podejściem do drukowania DOWOLNEGO typu liczby całkowitej jest rzutowanie na intmax_tlub uintmax_ti użycie odpowiednio "%jd"lub %ju. Jest to szczególnie przydatne na przykład w przypadku typów POSIX (lub innych systemów operacyjnych), które nie mają zdefiniowanych makr PRI * off_t.

R .. GitHub PRZESTAŃ POMÓC LODOWI
źródło