una son que oracion los formato especificadores c++ c visual-c++

c++ - son - especificadores de formato en c



__tribuir__((formato(printf, 1, 2))) para MSVC? (4)

Con GCC, puedo especificar __attribute__((format(printf, 1, 2))) , diciéndole al compilador que esta función toma los parámetros vararg que son especificadores de formato printf.

Esto es muy útil en los casos en que envuelvo, por ejemplo, la familia de funciones vsprintf. Puedo tener extern void log_error(const char *format, ...) __attribute__((format(printf, 1, 2)));

Y cada vez que llamo a esta función, gcc verificará que los tipos y el número de argumentos se ajusten a los especificadores de formato dados como lo haría para printf, y emitiría una advertencia si no.

¿El compilador de Microsoft C / C ++ tiene algo similar?


Como se mencionó previamente en @RustyX, la comprobación de formato printf ahora es compatible de forma predeterminada a partir de VC2015 . Eso es sin un /analyze análisis pase de análisis estático. Lamentablemente, aún no existe un mecanismo para marcar funciones de contenedor definidas por el usuario.

Esto sugiere la solución obvia de llamar a printf . Eso es definir una macro que invoca tanto la función definida por el usuario como la propia printf . Este último en un camino muerto para ser optimizado.

Esto tiene el beneficio adicional de lograr cierto nivel de portabilidad para otros compiladores.

int printf_wrapper_(const char *format, ...); #define printf_wrapper(...) / (printf || printf(__VA_ARGS__), printf_wrapper_(__VA_ARGS__))

El inconveniente es que el VC2015 realiza una eliminación rudimentaria del código muerto antes de la comprobación del formato, probando solo el código en vivo restante.

Por lo tanto, fallarán las expresiones condicionales sizeof o constante. Como regla general, si una compilación de depuración emite código de tiempo de ejecución, recibirá la advertencia, aunque los pases posteriores en compilaciones de lanzamiento aún pueden matar la llamada.

Por desgracia, esto lo convierte en una especie de objetivo móvil susceptible de cambiar en futuras versiones de compiladores. Aunque es relativamente benigno.


Hay un artículo interesante sobre el tema en Code Project: "Uso de plantillas de C ++ para la validación de inicio" por Alexander Gorobets http://www.codeproject.com/KB/cpp/ValidateprintfFunction.aspx

Lo he modificado para que tenga una macro PRINTF_VALIDATE(format, ...) que registra todos los errores de formato en el statup del programa (no hay necesidad de ejecutar el código en realidad). Produce algo como esto:

test.cpp(147) : error : ''printf'' format character ''f'' at position 1 does not match parameter type INT test.cpp(147) : error : ''printf'' too many arguments (3 instead of 2)

Uno puede usarlo por ejemplo así:

#define LOG(fmt, ...) do { PRINTF_VALIDATE(fmt, __VA_ARGS__); WriteLog(fmt, __VA_ARGS__); } while(0)

Esto no es tan útil como el soporte del compilador, pero funciona en Visual Studio 2005 ...


Mientras que GCC comprueba los especificadores de formato cuando -Wformat está habilitado, VC ++ no tiene dicha comprobación, incluso para las funciones estándar, por lo que no hay equivalente a esta __attribute__ porque no hay equivalente a -Whatformat.

Creo que el énfasis de Microsoft en C ++ (evidenciado por mantener el cumplimiento de la norma ISO para C ++ mientras que solo es compatible con C89) puede ser, en parte, la razón por la que VC ++ no cuenta con la verificación del especificador de formato; en C ++ usando los especificadores de formato <iostream> son innecesarios.


Usando Anotaciones SAL puede usar _Printf_format_string_ (a partir de VS2k8 o VS2k10) o __format_string (para VS2k5):

#undef FORMAT_STRING #if _MSC_VER >= 1400 # include <sal.h> # if _MSC_VER > 1400 # define FORMAT_STRING(p) _Printf_format_string_ p # else # define FORMAT_STRING(p) __format_string p # endif /* FORMAT_STRING */ #else # define FORMAT_STRING(p) p #endif /* _MSC_VER */ /* use /analyze or _USE_ATTRIBUTES_FOR_SAL for checking */ extern void log_error(FORMAT_STRING(const char* format), ...);