especificadores de formato printf para uint32_t y size_t

101

Tengo lo siguiente

size_t   i = 0;
uint32_t k = 0;

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

Recibo la siguiente advertencia al compilar:

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

Cuando ejecuté esto usando una férula, obtuve lo siguiente:

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

Muchas gracias por cualquier consejo,

ant2009
fuente
2
C89 no es compatible uint32_tcon <stdint.h>o <inttypes.h>; si desea utilizar esos tipos, debe actualizar a C89. Como extensión, es probable que GCC le permita usarlos, pero C89 no tenía tal soporte.
Jonathan Leffler
10
Y el modificador oficial de formato C99 para size_tes 'z', como en "%zu".
Jonathan Leffler
1
stackoverflow.com/questions/1401526/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Creo que la respuesta de @ kenny es mejor para uint32_t, pero falta size_t. La respuesta de @ u0b34a0f6ae incluye ambos.
jww
La segunda mención de C89 en el primer comentario de Jonathan Leffler debería ser C99
bph

Respuestas:

28

Parece que esperas size_tser el mismo que unsigned long(posiblemente 64 bits) cuando en realidad es un unsigned int(32 bits). Intente usar %zuen ambos casos.

Sin embargo, no estoy del todo seguro.

Rueda dentada
fuente
1
Sin advertencias al compilar. Sin embargo, al ejecutar splint obtengo lo siguiente: 1) printf (% u) espera unsigned int obtiene uint32_t: i 2) printf (% u) espera unsigned int gets size_t: k
ant2009
Entonces, suena como si férula fuera pedante. Probablemente esté usando los nombres de los tipos en el código fuente y no se dé cuenta de que son equivalentes. Me pregunto qué haría con la respuesta de @ KennyTM ... Ciertamente debería ser más portátil.
Rueda dentada
3
férula en realidad está haciendo lo correcto. El hecho de int32_tque esté inten su compilador / plataforma no significa que no pueda estar longen otro. Lo mismo para size_t. En realidad, se está esforzando y haciendo más trabajo para detectar este error de portabilidad, ya que la verificación fácil y natural sería simplemente respetar el typedef como lo hace el compilador.
R .. GitHub DEJA DE AYUDAR A ICE
4
-1, lo siento, no es portátil. Todo lo que se necesita es que los especificadores de formato y los tipos estén de acuerdo, y siempre puede transmitir para que eso sea cierto. long es al menos 32 bits, por lo que %lujunto con (unsigned long)ksiempre es correcto. size_tes más complicado, por lo que %zuse agregó en C99. Si no puede usar eso, trátelo como k( longes el tipo más grande en C89, size_tes muy poco probable que sea más grande).
u0b34a0f6ae
139

Tratar

#include <inttypes.h>
...

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

El zrepresenta un número entero de la misma longitud que size_t, y la PRIu32macro, definida en el encabezado C99inttypes.h , representa un número entero de 32 bits sin signo.

Kennytm
fuente
3
@robUK: Je. Le sugiero que presente un error para la férula.
kennytm
8
Esta es la respuesta correcta. Aunque mi recomendación personal es simplemente lanzar, por ejemplo printf( "%lu", (unsigned long )i ). De lo contrario, uno termina más tarde con un montón de advertencias en todo el código debido a un cambio de tipo.
Dummy00001
1
Esta es la respuesta correcta. Estoy de acuerdo con KennyTM sobre la presentación de un error por entablillado. Por cierto, "% zu" es el formato adecuado para size_t. No necesita ninguna de las macros PRI * para imprimir size_t.
R .. GitHub DEJA DE AYUDAR A ICE
1
Si mal no recuerdo,% zu es C99, y en la pregunta escribió 'C89'.
alcor
8
@alcor, sí, puso C89 (aparentemente la bandera del compilador gcc que está usando) pero lo está usando, uint32_tasí que en realidad es código C99, y debería compilarse como tal.
Colin D Bennett
28

Todo lo que se necesita es que los especificadores de formato y los tipos estén de acuerdo, y siempre puede transmitir para que eso sea cierto. longes de al menos 32 bits, por lo que %lujunto con (unsigned long)ksiempre es correcto:

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

size_tes más complicado, por lo que %zuse agregó en C99. Si no puede usar eso, trátelo como k( longes el tipo más grande en C89, size_tes muy poco probable que sea más grande).

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

Si no obtiene los especificadores de formato correctos para el tipo que está pasando, printfhará el equivalente a leer demasiada o muy poca memoria de la matriz. Siempre que use conversiones explícitas para emparejar tipos, es portátil.

u0b34a0f6ae
fuente
17

Si no desea usar las macros PRI *, otro enfoque para imprimir CUALQUIER tipo de entero es convertir a intmax_to uintmax_ty usar "%jd"o %ju, respectivamente. Esto es especialmente útil para los tipos POSIX (u otros sistemas operativos) que no tienen macros PRI * definidas, por ejemplo off_t.

R .. GitHub DEJA DE AYUDAR A ICE
fuente