2010-07-02 12 views
81

Tengo el siguienteespecificadores de formato printf para uint32_t y size_t

size_t i = 0; 
uint32_t k = 0; 

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

me sale el siguiente mensaje de advertencia al compilar:

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

Cuando me encontré con esto usando una férula me dieron el siguiente:

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

Muchas gracias por cualquier consejo,

+1

C89 no admite 'uint32_t' de' 'o' '; si desea utilizar esos tipos, debe actualizar a C89. Como una extensión, es probable que GCC le permita usarlos, pero C89 no tenía dicho soporte. –

+9

Y el modificador oficial de formato C99 para 'size_t' es 'z', como en' "% zu" '. –

+1

http://stackoverflow.com/questions/1401526/how-to-use-printf-to-display-off-t-nlink-t-size-t-and-other-special-types –

Respuesta

18

Parece que está esperando que size_t sea lo mismo que unsigned long (posiblemente 64 bits) cuando en realidad es unsigned int (32 bits). Intente usar %zu en ambos casos.

Aunque no estoy del todo seguro.

+1

Sin advertencias durante la compilación.Sin embargo, al ejecutar splint obtengo lo siguiente: 1) printf (% u) espera unsigned int gets uint32_t: i 2) printf (% u) espera unsigned int gets size_t: k – ant2009

+0

Parece que splint es solo pedantic, entonces. Probablemente esté deshabilitando los nombres de los tipos en el código fuente y no se da cuenta de que son equivalentes. Me pregunto qué haría con la respuesta de @ KennyTM ... Ciertamente debería ser más portátil. – Cogwheel

+3

splint está haciendo lo correcto. El hecho de que 'int32_t' sea' int' en su compilador/plataforma no significa que no sea 'largo' en otro. Lo mismo para 'size_t'. En realidad, se está desviando y haciendo ** más ** trabajo para detectar este error de portabilidad, ya que la verificación fácil y natural sería simplemente honrar al tipo como lo hace el compilador. –

114

Trate

#include <inttypes.h> 
... 

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

El z representa un número entero de longitud mismo que size_t, y la PRIu32 macro, defined in the C99 header inttypes.h, representa un entero sin signo de 32 bits.

+0

Compila sin advertencias. Pero a la férula no le gusta. Código de formato no reconocido:% zu. Y para el segundo. Error de análisis. (Para obtener ayuda sobre los errores de análisis, vea splint -help parseerrors.) *** No se puede continuar. – ant2009

+3

@robUK: Heh. Le sugiero que presente un error para férula. – kennytm

+6

Esta es la respuesta correcta. Aunque mi recomendación personal es simplemente lanzar, p. 'printf ("% lu ", (unsigned long) i)'. De lo contrario, uno termina después con un montón de advertencias en todo el código debido a un cambio de tipo. – Dummy00001

16

Si no desea utilizar las macros PRI *, otro enfoque para la impresión CUALQUIER tipo entero es para echar a intmax_t o uintmax_t y utilizar "%jd" o %ju, respectivamente. Esto es especialmente útil para los tipos POSIX (u otro sistema operativo) que no tienen macros PRI * definidas, por ejemplo off_t.

21

Todo lo que se necesita es que los especificadores de formato y los tipos estén de acuerdo, y siempre se puede convertir para que esto sea cierto. long es al menos 32 bits, por lo %lu junto con (unsigned long)k siempre es correcta:

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

size_t es más complicado, que es la razón por %zu se añadió en C99. Si no puede usar eso, trátelo como k (long es el tipo más grande en C89, size_t es 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 usted no recibe los especificadores de formato correcto para el tipo está de paso, a continuación, printf hará el equivalente de la lectura de la memoria demasiado o demasiado poco fuera de la matriz. Siempre que use conversiones explícitas para hacer coincidir tipos, es portátil.

Cuestiones relacionadas