Estoy tratando de imprimir tipos como off_t
y size_t
. ¿Cuál es el marcador de posición correcto para printf()
que sea portátil ?
¿O hay una forma completamente diferente de imprimir esas variables?
Estoy tratando de imprimir tipos como off_t
y size_t
. ¿Cuál es el marcador de posición correcto para printf()
que sea portátil ?
¿O hay una forma completamente diferente de imprimir esas variables?
Respuestas:
Puede usar z
para size_t y t
ptrdiff_t como en
printf("%zu %td", size, ptrdiff);
Pero mi página de manual dice que alguna biblioteca más antigua usaba un carácter diferente z
y desalienta su uso. Sin embargo, está estandarizado (según el estándar C99). Para aquellos intmax_t
y int8_t
de stdint.h
y así sucesivamente, hay macros que puede usar, como dijo otra respuesta:
printf("value: %" PRId32, some_int32_t);
printf("value: %" PRIu16, some_uint16_t);
Se enumeran en la página de manual de inttypes.h
.
Personalmente, simplemente emitiría los valores unsigned long
o me long
gustaría que otra respuesta me recomendara. Si usa C99, puede (y debería, por supuesto) emitir unsigned long long
o long long
usar los formatos %llu
o %lld
respectivamente.
%zd
con a size_t
es un comportamiento indefinido debido a la falta de coincidencia de firma (C99 7.19.6.1 # 9). Debe ser %zu
.
%zd
con un size_t
comportamiento indefinido se obtiene de ese párrafo o de cualquier otro. De hecho, la definición de %z
en # 7 permite explícitamente %d
con size_t
y el tipo con signo correspondiente, y §6.2.5 # 9 permite explícitamente usar valores de tipos sin signo donde se espera el tipo con signo correspondiente, siempre que el valor sea un valor no negativo válido del tipo firmado.
Para imprimir off_t
:
printf("%jd\n", (intmax_t)x);
Para imprimir size_t
:
printf("%zu\n", x);
Para imprimir ssize_t
:
printf("%zd\n", x);
Consulte 7.19.6.1/7 en el estándar C99, o la documentación POSIX más conveniente de los códigos de formato:
http://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html
Si su implementación no es compatible con esos códigos de formato (por ejemplo, porque está en C89), entonces tiene un pequeño problema, ya que AFAIK no hay tipos enteros en C89 que tengan códigos de formato y se garantice que sean tan grandes como estos tipos Por lo tanto, debe hacer algo específico de implementación.
Por ejemplo, si su compilador tiene long long
y su biblioteca estándar es compatible %lld
, puede esperar con confianza que sirva en lugar de intmax_t
. Pero si no es así, tendrá que recurrir a long
, lo que podría fallar en algunas otras implementaciones porque es demasiado pequeño.
ssize_t
tenga el mismo tamaño size_t
, por lo que un código verdaderamente portátil debería convertirlo intmax_t
e imprimirlo de la %jd
misma manera off_t
.
Para Microsoft, la respuesta es diferente. VS2013 es en gran medida compatible con C99 pero "[t] he hh, j, z y t prefijos de longitud no son compatibles". Para size_t ", es decir, __int32 sin signo en plataformas de 32 bits, __int64 sin signo en plataformas de 64 bits", utilice el prefijo I (ojo de mayúscula) con el especificador de tipo o, u, x o X. Consulte la especificación de tamaño VS2013
En cuanto a off_t, se define como largo en VC \ include \ sys \ types.h.
off_t
es siempre long
eso lo haría de 32 bits (incluso Windows de 64 bits usa 32 bits para long
).
¿Qué versión de C estás usando?
En C90, la práctica estándar es emitir a largo con o sin signo, según corresponda, e imprimir en consecuencia. He visto% z para size_t, pero Harbison y Steele no lo mencionan en printf (), y en cualquier caso eso no lo ayudaría con ptrdiff_t o lo que sea.
En C99, los diversos tipos _t vienen con sus propias macros printf, por lo que algo como "Size is " FOO " bytes."
no sé los detalles, pero eso es parte de un archivo de inclusión de formato numérico bastante grande.
Querrá usar las macros de formato de inttypes.h.
Consulte esta pregunta: ¿ Cadena de formato multiplataforma para variables de tipo size_t?
off_t
tipo es más grande que un puntero en cualquier sistema de 32 bits que admita archivos grandes (que actualmente es la mayoría de los sistemas de 32 bits).
En cuanto a man 3 printf
Linux, OS X y OpenBSD, todos muestran soporte %z
para size_t
y %t
para ptrdiff_t
(para C99), pero ninguno de ellos menciona off_t
. Las sugerencias en la naturaleza generalmente ofrecen la %u
conversión para off_t
, que es "lo suficientemente correcta" hasta donde puedo decir (ambas unsigned int
y off_t
varían de manera idéntica entre los sistemas de 64 bits y 32 bits).
unsigned int
y 64 bits off_t
. Por lo tanto, el reparto provocaría la pérdida de datos.
Vi esta publicación al menos dos veces, porque la respuesta aceptada es difícil de recordar para mí (rara vez uso z
o j
marcas y parece que no son independientes de la plataforma ).
El estándar nunca dice claramente la longitud exacta de los datos size_t
, por lo que le sugiero que primero verifique la longitud size_t
en su plataforma y luego seleccione uno de ellos:
if sizeof(size_t) == 4 use PRIu32
if sizeof(size_t) == 8 use PRIu64
Y sugiero usar stdint
tipos en lugar de tipos de datos sin procesar para la consistencia.
%zu
se puede usar para imprimir size_t
valores. Definitivamente no se debe recurrir al uso de un especificador de formato uint32_t
/ uint64_t
para imprimir size_t
, ya que no hay garantía de que esos tipos sean compatibles.
Según recuerdo, la única forma portátil de hacerlo es lanzar el resultado a "unsigned long int" y usarlo %lu
.
printf("sizeof(int) = %lu", (unsigned long) sizeof(int));
long long
no existe en el estándar C ++ y, por lo tanto, es inherentemente no portátil.
fopen
,fseek
, etc en Mac OS Xoff_t
se utiliza para el desplazamiento.