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,


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


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.


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.


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.


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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.