Tengo un código C ++ que imprime un size_t
:
size_t a;
printf("%lu", a);
Me gustaría que esto se compilara sin advertencias en arquitecturas de 32 y 64 bits.
Si esto fuera C99, podría usar printf("%z", a);
. Pero AFAICT %z
no existe en ningún dialecto estándar de C ++. Entonces, en cambio, tengo que hacer
printf("%lu", (unsigned long) a);
que es realmente feo.
Si no hay ninguna facilidad para imprimir size_t
mensajes de correo electrónico integrados en el lenguaje, me pregunto si es posible escribir un contenedor printf o algo así que inserte las conversiones apropiadas en size_t
los mensajes de correo electrónico para eliminar las advertencias falsas del compilador mientras se mantienen las buenas.
¿Algunas ideas?
Editar Para aclarar por qué estoy usando printf: tengo una base de código relativamente grande que estoy limpiando. Usa envoltorios printf para hacer cosas como "escribir una advertencia, registrarla en un archivo y posiblemente salir del código con un error". Podría reunir suficiente C ++ - foo para hacer esto con un contenedor cout, pero prefiero no cambiar todas las llamadas warn () en el programa solo para deshacerme de algunas advertencias del compilador.
"%l"
? ¿No será siempre del tamaño correcto? ¿O importa la portabilidad?Respuestas:
La mayoría de los compiladores tienen su propio especificador
size_t
yptrdiff_t
argumentos, Visual C ++, por ejemplo, usa% Iu y% Id respectivamente, creo que gcc le permitirá usar% zu y% zd.Podrías crear una macro:
Uso:
fuente
%z
es compatible o no, depende del tiempo de ejecución, no del compilador.__GNUC__
Por lo tanto, usar es un poco problemático si mezcla GCC / mingw con msvcrt (y sin usar la printf aumentada de mingw).El
printf
especificador de formato%zu
funcionará bien en sistemas C ++; no hay necesidad de hacerlo más complicado.fuente
C ++ 11
C ++ 11 importa C99, por lo que
std::printf
debería admitir el%zu
especificador de formato C99 .C ++ 98
En la mayoría de las plataformas,
size_t
yuintptr_t
son equivalentes, en cuyo caso puede utilizar laPRIuPTR
macro definida en<cinttypes>
:Si realmente quieres estar seguro, envía
uintmax_t
y usaPRIuMAX
:fuente
En windows y la implementación de printf de Visual Studio
funciona para mi. ver msdn
fuente
VS 2008
también. También tenga en cuenta que se puede usar%Id
,%Ix
y%IX
también.Ya que está usando C ++, ¿por qué no usar IOStreams? Eso debería compilarse sin advertencias y hacer lo correcto con reconocimiento de tipos, siempre que no esté utilizando una implementación de C ++ con muerte cerebral que no defina un
operator <<
forsize_t
.Cuando la salida real se tiene que hacer con
printf()
, todavía se puede combinar con iostreams para conseguir un comportamiento de tipo seguro:No es súper eficiente, pero su caso anterior trata con E / S de archivos, por lo que ese es su cuello de botella, no este código de formato de cadena.
fuente
std::stringstream
lugar de transmisiones IO.printf("x=%i, y=%i;\n", x, y);
vscout << "x=" << x << ", y=" << y << ";" << std::endl;
.aquí hay una posible solución, pero no es muy bonita ...
fuente
La biblioteca fmt proporciona una implementación portátil rápida (y segura) de
printf
incluir elz
modificador parasize_t
:Además de eso, es compatible con la sintaxis de cadenas de formato similar a Python y captura información de tipo para que no tenga que proporcionarla manualmente:
Ha sido probado con los principales compiladores y proporciona resultados consistentes en todas las plataformas.
Descargo de responsabilidad : soy el autor de esta biblioteca.
fuente
El tipo efectivo subyacente a size_t depende de la implementación . C Standard lo define como el tipo devuelto por el operador sizeof; aparte de no estar firmado y ser una especie de tipo integral, size_t puede ser prácticamente cualquier tamaño cuyo tamaño pueda acomodar el valor más grande que se espera que devuelva sizeof ().
En consecuencia, la cadena de formato que se utilizará para size_t puede variar según el servidor. Siempre debe tener la "u", pero puede ser l o d o tal vez algo más ...
Un truco podría ser convertirlo en el tipo integral más grande en la máquina, asegurando que no se pierdan en la conversión y luego usar la cadena de formato asociada con este tipo conocido.
fuente
size_t
s al tipo integral más grande en la máquina y usar la cadena de formato asociada con este tipo. Mi pregunta es: ¿Hay alguna manera de hacer esto mientras mantengo el código limpio (advertencias solo para errores legítimos de cadena de formato de printf, sin cambios desagradables, etc.)? Podría escribir un contenedor que cambie la cadena de formato, pero luego GCC no podría darme advertencias cuando legítimamente estropeé mi cadena de formato.Más adelante en el código:
my::printf("test ", 1, '\t', 2.0);
fuente