variable sintaxis pantalla lenguaje imprimir ejemplos dev datos como c printf

sintaxis - ¿Cómo se puede imprimir una variable size_t usando la familia printf?



printf y scanf en dev c++ (12)

¿Le avisará si pasa un entero sin signo de 32 bits a un formato% lu? Debería estar bien ya que la conversión está bien definida y no pierde ninguna información.

He oído que algunas plataformas definen macros en <inttypes.h> que puede insertar en el formato de cadena literal pero no veo ese encabezado en mi compilador de Windows C ++, lo que implica que puede que no sea multiplataforma.

Tengo una variable de tipo size_t , y quiero imprimirla usando printf() . ¿Qué especificador de formato utilizo para imprimirlo de forma portátil?

En la máquina de 32 bits, %u parece correcto. Compilé con g ++ -g -W -Wall -Werror -ansi -pedantic, y no hubo ninguna advertencia. Pero cuando compilo ese código en una máquina de 64 bits, produce una advertencia.

size_t x = <something>; printf( "size = %u/n", x ); warning: format ''%u'' expects type ''unsigned int'', but argument 2 has type ''long unsigned int''

La advertencia desaparece, como se esperaba, si la cambio a %lu .

La pregunta es, ¿cómo puedo escribir el código para que compile sin avisos en máquinas de 32 y 64 bits?

Edición: supongo que una respuesta podría ser "convertir" la variable en un unsigned long , e imprimir con %lu . Eso funcionaría en ambos casos. Estoy mirando si hay alguna otra idea.


Ampliando la respuesta de Adam Rosenfield para Windows.

Probé este código con la actualización de VS2013 Update 4 y VS2015:

// test.c #include <stdio.h> #include <BaseTsd.h> // see the note below int main() { size_t x = 1; SSIZE_T y = 2; printf("%zu/n", x); // prints as unsigned decimal printf("%zx/n", x); // prints as hex printf("%zd/n", y); // prints as signed decimal return 0; }

VS2015 genera salidas binarias:

1
1
2

mientras que el generado por VS2013 dice:

zu
zx
zd

Nota: ssize_t es una extensión POSIX y SSIZE_T es algo similar en los tipos de datos de Windows , por lo que <BaseTsd.h> referencia <BaseTsd.h> .

Además, a excepción de los siguientes encabezados C99 / C11, todos los encabezados C99 están disponibles en la vista previa de VS2015:

C11 - <stdalign.h> C11 - <stdatomic.h> C11 - <stdnoreturn.h> C99 - <tgmath.h> C11 - <threads.h>

Además, <uchar.h> C11 ahora se incluye en la última vista previa.

Para obtener más detalles, consulte esta lista old y la new para el cumplimiento estándar.


C99 define "% zd", etc. para eso. (gracias a los comentaristas) No hay un especificador de formato portátil para C ++; podría usar %p , que es una palabra errónea en estos dos escenarios, pero tampoco es una opción portátil, y da el valor en hexadecimal.

Alternativamente, use alguna transmisión (por ejemplo, cadena de caracteres) o un reemplazo seguro de printf como Boost Format . Entiendo que este consejo es solo de uso limitado (y requiere C ++). (Hemos utilizado un enfoque similar adaptado a nuestras necesidades al implementar el soporte de Unicode).

El problema fundamental para C es que el uso de puntos suspensivos de impresión no es seguro por su diseño: debe determinar el tamaño del argumento adicional a partir de los argumentos conocidos, por lo que no se puede arreglar para admitir "lo que sea que tenga". Entonces, a menos que tu compilador implemente algunas extensiones propietarias, estás fuera de suerte.


Como dijo AraK, la interfaz de flujos de c ++ siempre funcionará de manera portátil.

std :: size_t s = 1024; std :: cout << s; // o cualquier otro tipo de flujo como stringstream!

Si desea C stdio, no hay una respuesta portátil para esto en ciertos casos de "portátil". Y se pone feo ya que, como has visto, elegir las marcas de formato incorrecto puede producir una advertencia del compilador o dar un resultado incorrecto.

C99 intentó resolver este problema con los formatos inttypes.h como "%" PRIdMAX "/ n". Pero al igual que con "% zu", no todos admiten c99 (como MSVS antes de 2013). Hay archivos "msinttypes.h" flotando alrededor para lidiar con esto.

Si realiza la conversión a un tipo diferente, dependiendo de los indicadores, puede recibir una advertencia del compilador para el truncamiento o un cambio de signo. Si vas por esta ruta, elige un tipo de tamaño fijo relevante más grande. Debería funcionar uno de los largos sin signo largos y "% llu" o los largos sin firmar "% lu", pero también puede ralentizar las cosas en un mundo de 32 bits como demasiado grande. (Editar: mi Mac emite una advertencia en 64 bits para que% llu no coincida con size_t, aunque% lu,% llu y size_t sean del mismo tamaño. Y% lu y% llu no son del mismo tamaño en mi MSVS2012. puede que necesites lanzar + usar un formato que coincida.)

Para el caso, puede ir con tipos de tamaño fijo, como int64_t. ¡Pero espera! Ahora volvemos a c99 / c ++ 11, y MSVS anterior falla nuevamente. Además, también tiene conversiones (por ejemplo, map.size () no es un tipo de tamaño fijo).

Puede utilizar un encabezado de terceros o una biblioteca como boost. Si aún no está utilizando uno, es posible que no desee inflar su proyecto de esa manera. Si está dispuesto a agregar uno solo para este problema, ¿por qué no usa las secuencias de c ++ o la compilación condicional?

Por lo tanto, se reduce a las secuencias de C ++, la compilación condicional, los marcos de terceros o algún tipo de dispositivo portátil que funcione para usted.


En algunas plataformas y para algunos tipos hay especificadores de conversión específicos de printf disponibles, pero a veces uno tiene que recurrir a la conversión de tipos más grandes.

He documentado este problema complicado aquí, con el código de ejemplo: http://www.pixelbeat.org/programming/gcc/int_types/ y lo actualizo periódicamente con información sobre nuevas plataformas y tipos.


Para C89, use %lu y convierta el valor a un unsigned long :

size_t foo; ... printf("foo = %lu/n", (unsigned long) foo);

Para C99 y versiones posteriores, use %zu :

size_t foo; ... printf("foo = %zu/n", foo);


Para aquellos que hablan de hacer esto en C ++, que no necesariamente admite las extensiones C99, entonces recomiendo de todo corazón boost :: format. Esto hace que la pregunta de tamaño de tipo size_t sea discutible:

std::cout << boost::format("Sizeof(Var) is %d/n") % sizeof(Var);

Ya que no necesita especificadores de tamaño en formato boost ::, solo puede preocuparse sobre cómo desea mostrar el valor.


Parece que varía según el compilador que estés usando (blech):

... y, por supuesto, si está utilizando C ++, puede usar cout lugar de lo sugerido por AraK .


Si desea imprimir el valor de size_t como una cadena, puede hacer esto:

char text[] = "Lets go fishing in stead of sitting on our but !!"; size_t line = 2337200120702199116; /* on windows I64x or I64d others %lld or %llx if it works %zd or %zx */ printf("number: %I64d/n",*(size_t*)&text); printf("text: %s/n",*(char(*)[])&line);

el resultado es:

Número: 2337200120702199116

texto: ¡Vamos a pescar en lugar de sentarnos en nuestro pero!

Edición: al volver a leer la pregunta debido a los votos a la baja, noté que su problema no es% llu o% I64d, pero el tipo size_t en diferentes máquinas ve esta pregunta https://.com/a/918909/1755797
http://www.cplusplus.com/reference/cstdio/printf/

size_t es un unsigned int en una máquina de 32 bits y un unsigned long long int en 64 bits
pero% ll siempre espera un int largo y largo sin firmar.

size_t varía en longitud en diferentes sistemas operativos mientras que% llu es el mismo


Usa el modificador z :

size_t x = ...; ssize_t y = ...; printf("%zu/n", x); // prints as unsigned decimal printf("%zx/n", x); // prints as hex printf("%zd/n", y); // prints as signed decimal


printf("size = %zu/n", sizeof(thing) );


std::size_t s = 1024; std::cout << s; // or any other kind of stream like stringstream!