ssize_t size_t c++ c cross-platform printf size-t

c++ - ssize_t - size_t c



Secuencia de formato de plataforma cruzada para variables del tipo size_t? (9)

La macro PRIuPTR (de <inttypes.h>) define un formato decimal para uintptr_t , que siempre debe ser lo suficientemente grande como para poder convertirle un size_t sin truncar, por ej.

fprintf(stream, "Your size_t var has value %" PRIuPTR ".", (uintptr_t) your_var);

En un proyecto de plataforma cruzada c / c ++ (Win32, Linux, OSX), necesito usar las funciones * printf para imprimir algunas variables de tipo size_t. En algunos entornos, size_t''s son 8 bytes y en otros son 4. En glibc tengo% zd, y en Win32 puedo usar % Id . ¿Hay una forma elegante de manejar esto?


Dan Saks escribió un artículo en Embedded Systems Design que cubría este asunto. Según Dan,% zu es la forma estándar, pero pocos compiladores lo admiten. Como alternativa, recomendó usar% lu junto con un molde explícito del argumento a unsigned long:

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


Lo único que se me ocurre es el típico:

#ifdef __WIN32__ // or whatever #define SSIZET_FMT "%ld" #else #define SSIZET_FMT "%zd" #endif

y luego aprovechar el plegado constante:

fprintf(stream, "Your size_t var has value " SSIZET_FMT ".", your_var);


No conozco ninguna solución satisfactoria, pero podría considerar una función especializada para formatear items size_t en una cadena e imprimir la cadena.

(Alternativamente, si puede salirse con la suya, el formato boost :: maneja este tipo de cosas con facilidad).


Use el boost::format . Es seguro, así que imprimirá size_t correctamente con %d , también no necesita recordar poner c_str() en std::string s cuando lo usa, e incluso si pasa un número a %s o viceversa , funcionará


Solo tiene que encontrar un tipo entero con la clase de almacenamiento más grande, asignarle el valor y luego usar la cadena de formato adecuada para el tipo más grande. Tenga en cuenta que esta solución funcionará para cualquier tipo (ptrdiff_t, etc.), no solo size_t.

Lo que quiere usar es uintmax_t y la macro de formato PRIuMAX. Para Visual C ++, necesitará descargar los encabezados stdint.h e inttypes.h compatibles con c99, ya que Microsoft no los proporciona.

Ver también

http://www.embedded.com/columns/technicalinsights/204700432

Este artículo corrige los errores en el artículo citado por Frederico.


Mi elección para ese problema es simplemente convertir el argumento size_t en unsigned long y usar% lu en todas partes, esto por supuesto solo donde no se espera que los valores excedan 2 ^ 32-1. Si esto es demasiado corto para usted, siempre puede convertir a unsigned long long y formatearlo como% llu.

De cualquier forma, tus cuerdas nunca serán incómodas.


En realidad, hay dos preguntas aquí. La primera pregunta es cuál es la cadena de especificador printf correcta para las tres plataformas. Tenga en cuenta que size_t es un tipo sin firmar.

En Windows , use " %Iu ".

En Linux y OSX , use " %zu ".

La segunda pregunta es cómo admitir múltiples plataformas, dado que cosas como las cadenas de formato pueden ser diferentes en cada plataforma. Como han señalado otras personas, usar #ifdef pone feo rápidamente.

En su lugar, escriba un archivo MAKE o proyecto por separado para cada plataforma de destino. Luego consulte el especificador por algún nombre de macro en sus archivos de origen, definiendo la macro apropiadamente en cada archivo MAKE. En particular, tanto GCC como Visual Studio aceptan un interruptor ''D'' para definir macros en la línea de comando.

Si tu sistema de compilación es muy complicado (múltiples opciones de compilación, fuentes generadas, etc.), mantener 3 makefiles separados puede ser difícil de manejar, y vas a tener que usar algún tipo de sistema de compilación avanzado como CMake o las autotools de GNU. Pero el principio básico es el mismo: use el sistema de compilación para definir las macros específicas de la plataforma en lugar de poner la lógica de detección de plataforma en sus archivos fuente.


size_t es un tipo sin signo de al menos 16 bits. Se ven a menudo anchos de 32 y 64.

printf("%zu/n", some_size_t_object); // Standard since C99

Más arriba es la mejor manera de avanzar, pero si el código también necesita un puerto para plataformas anteriores a C99, encubrir el valor a algún tipo ancho. unsigned long es un candidato razonable pero puede no existir.

// OK, yet insufficient with large sizes > ULONG_MAX printf("%lu/n", (unsigned long) some_size_t_object);

o con código condicional

#ifdef ULLONG_MAX printf("%llu/n", (unsigned long long) some_size_t_object); #else printf("%lu/n", (unsigned long) some_size_t_object); #endif

Por último, considere el double . Es un poco ineficiente pero debe manejar todas las plataformas antiguas y nuevas hasta aproximadamente los años 2030-2040 teniendo en cuenta la ley de Moore cuando el double puede carecer de un resultado preciso.

printf("%.0f/n", (double) some_size_t_object);