#define __STDC_WANT_LIB_EXT1__ 1 #include <stdio.h> // <cstdio> en C++ #include <stdarg.h> // <cstdarg> en C++
int vfprintf_s( FILE * restrict stream, const char * restrict format, va_list arguments ); // Depuis C11 int vprintf_s( const char * restrict format, va_list arguments ); // Depuis C11 int vsprintf_s( char * restrict buffer, rsize_t bufferSize, const char * restrict format, va_list arguments ); // Depuis C11 int vsnprintf_s( char * restrict buffer, rsize_t bufferSize, const char * restrict format, va_list arguments ); // Depuis C11
Ces fonctions sont les versions basées sur va_list des fonctions sécurisées
fprintf_s, printf_s, sprintf_s et snprintf_s.
Elles appartiennent à l'annexe K du standard C11, aussi appelée bounds-checking interfaces.
__STDC_WANT_LIB_EXT1__
avant l'inclusion des entêtes standards. Vous pouvez ensuite tester la présence de
__STDC_LIB_EXT1__.
Comme les fonctions vfprintf, vprintf,
vsprintf et vsnprintf,
ces variantes reçoivent une liste de paramètres variables déjà capturée dans une variable
de type va_list.
Les versions suffixées par _s ajoutent des contrôles d'exécution. Par exemple, elles
permettent de détecter certains paramètres invalides, comme un pointeur nul ou une taille de buffer
incohérente. En cas de violation d'une contrainte d'exécution, le gestionnaire de contraintes de
l'implémentation peut être invoqué.
Les fonctions vsprintf_s et vsnprintf_s reçoivent la taille du buffer via un
paramètre de type rsize_t. Cette taille permet à la fonction de vérifier que l'écriture
reste compatible avec la zone mémoire disponible.
Les prototypes C11 de ces fonctions utilisent le mot clé restrict. Ce mot clé avait
déjà été introduit dans C99 et indique que les zones mémoire pointées par les paramètres
concernés ne doivent pas se recouvrir. Cela permet de mieux documenter les contraintes d'appel et
peut aider le compilateur à optimiser le code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#define __STDC_WANT_LIB_EXT1__ 1 #include <stdarg.h> #include <stdio.h> #ifdef __STDC_LIB_EXT1__ int buildMessage( char * buffer, rsize_t bufferSize, const char * format, ... ) { va_list arguments; va_start( arguments, format ); int result = vsnprintf_s( buffer, bufferSize, format, arguments ); va_end( arguments ); return result; } #endif int main() { #ifdef __STDC_LIB_EXT1__ char buffer[32]; buildMessage( buffer, sizeof buffer, "Ligne %d : %s", 12, "OK" ); printf( "%s\n", buffer ); #else puts( "Annexe K non disponible sur cette implementation." ); #endif return 0; } |
Sur une implémentation qui ne propose pas l'annexe K, l'affichage produit sera :
$> gcc -o Sample -Wall Sample.c $> ./Sample Annexe K non disponible sur cette implementation. $>
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :