Partager via


vsnprintf, , _vsnprintf_vsnprintf_l, , _vsnwprintf_vsnwprintf_l

Écrivez une sortie formatée à l’aide d’un pointeur vers une liste d’arguments. Des versions plus sécurisées de ces fonctions sont disponibles ; voir vsnprintf_s, _vsnprintf_s, _vsnprintf_s_l, _vsnwprintf_s, _vsnwprintf_s_l.

Syntaxe

int vsnprintf(
   char *buffer,
   size_t count,
   const char *format,
   va_list argptr
);

int _vsnprintf(
   char *buffer,
   size_t count,
   const char *format,
   va_list argptr
);

int _vsnprintf_l(
   char *buffer,
   size_t count,
   const char *format,
   _locale_t locale,
   va_list argptr
);

int _vsnwprintf(
   wchar_t *buffer,
   size_t count,
   const wchar_t *format,
   va_list argptr
);

int _vsnwprintf_l(
   wchar_t *buffer,
   size_t count,
   const wchar_t *format,
   _locale_t locale,
   va_list argptr
);

template <size_t size>
int vsnprintf(
   char (&buffer)[size],
   size_t count,
   const char *format,
   va_list argptr
); // C++ only

template <size_t size>
int _vsnprintf(
   char (&buffer)[size],
   size_t count,
   const char *format,
   va_list argptr
); // C++ only

template <size_t size>
int _vsnprintf_l(
   char (&buffer)[size],
   size_t count,
   const char *format,
   _locale_t locale,
   va_list argptr
); // C++ only

template <size_t size>
int _vsnwprintf(
   wchar_t (&buffer)[size],
   size_t count,
   const wchar_t *format,
   va_list argptr
); // C++ only

template <size_t size>
int _vsnwprintf_l(
   wchar_t (&buffer)[size],
   size_t count,
   const wchar_t *format,
   _locale_t locale,
   va_list argptr
); // C++ only

Paramètres

buffer
Emplacement de stockage pour la sortie.

count
Nombre maximum de caractères à écrire. Pour les fonctions qui prennent wchar_t, c’est le nombre de caractères larges à écrire.

format
Spécification du format.

argptr
Pointeur vers la liste des arguments.

locale
Locale à utiliser.

Pour plus d’informations, consultez Syntaxe de spécification de format.

Valeur retournée

Nombre de caractères écrits, sans compter la fin NULLou une valeur négative en cas d’erreur de sortie.

Pour plus d’informations, consultez la section Résumé du comportement .

Remarques

Chacune de ces fonctions prend un pointeur vers une liste d’arguments, puis formate les données et écrit jusqu’en count caractères dans la mémoire pointée par buffer. La vsnprintf fonction écrit toujours un terminateur null, même si elle tronque la sortie. Lorsque vous utilisez _vsnprintf et _vsnwprintf, la mémoire tampon n’est terminée par un caractère null que s’il y a de la place à la fin (c’est-à-dire si le nombre de caractères à écrire est inférieur à count).

À partir de l’UCRT dans Visual Studio 2015 et Windows 10, vsnprintf n’est plus identique à _vsnprintf. La vsnprintf fonction est conforme à la norme C99 ; _vsnprintf elle est conservée pour des raisons de compatibilité descendante avec le code plus ancien. La différence est que si vous n’avez plus de mémoire tampon, vsnprintf la valeur null met fin à la fin de la mémoire tampon et renvoie le nombre de caractères qui auraient été nécessaires, tandis _vsnprintf que la valeur n’est pas définie sur la valeur null de la mémoire tampon et renvoie -1. Inclut également un caractère supplémentaire dans la sortie, _vsnprintf() car il ne met pas fin à la mémoire tampon de manière nulle.

Important

Pour éviter certains types de risques de sécurité, assurez-vous qu’il format ne s’agit pas d’une chaîne définie par l’utilisateur. Pour plus d’informations, consultez Solutions contre les dépassements de mémoire tampon. À partir de Windows 10 version 2004 (build 19041), la printf famille de fonctions imprime des nombres à virgule flottante exactement représentables selon les règles d’arrondi IEEE 754. Dans les versions précédentes de Windows, les nombres à virgule flottante se terminant par « 5 » étaient toujours arrondis à la hausse. L’IEEE 754 stipule qu’ils doivent arrondir au chiffre pair le plus proche (également connu sous le nom d'« arrondi du banquier »). Par exemple, les deux printf("%1.0f", 1.5) et printf("%1.0f", 2.5) doivent être arrondis à 2. Auparavant, 1,5 s’arrondissait à 2 et 2,5 à 3. Ce changement n’affecte que les numéros exactement représentables. Par exemple, 2,35 (qui, lorsqu’il est représenté en mémoire, est plus proche de 2,350000000000008) continue d’arrondir à 2,4. L’arrondi effectué par ces fonctions respecte désormais également le mode d’arrondi en virgule flottante défini par fesetround. Auparavant, l’arrondi choisissait toujours le FE_TONEAREST comportement. Cette modification affecte uniquement les programmes créés à l’aide de Visual Studio 2019 version 16.2 et ultérieure. Pour utiliser le comportement d’arrondi à virgule flottante héritée, liez avec legacy_stdio_float_rounding.obj.

Remarque

Pour vous assurer qu’il y a de la place pour la valeur null de fin lors de l’appel de _vsnprintf, _vsnprintf_l_vsnwprintfet _vsnwprintf_l, assurez-vous que est count strictement inférieur à la longueur de la mémoire tampon et initialisez la mémoire tampon à null avant d’appeler la fonction.

Étant donné que vsnprintf la valeur null est toujours écrite, le count paramètre peut être égal à la taille de la mémoire tampon.

Les versions de ces fonctions avec le _l suffixe sont identiques, sauf qu’elles utilisent le paramètre locale passé à la place de la locale du thread actuel.

En C++, ces fonctions ont des surcharges de modèle qui appellent les homologues plus récents et sécurisés de ces fonctions. Pour plus d'informations, consultez Sécuriser les surcharges de modèle.

Résumé du comportement

Pour le tableau suivant :

  • Soit sizeOfBuffer la taille de buffer. Si la fonction prend une char mémoire tampon, la taille est exprimée en octets. Si la fonction prend une wchar_t mémoire tampon, la taille spécifie le nombre de mots de 16 bits.
  • Soit len la taille des données formatées. Si la fonction prend une char mémoire tampon, la taille est exprimée en octets. Si la fonction prend une wchar_t mémoire tampon, la taille spécifie le nombre de mots de 16 bits.
  • Les caractères font référence aux char caractères des fonctions qui prennent une char mémoire tampon et aux wchar_t caractères des fonctions qui prennent une wchar_t mémoire tampon.
  • Pour plus d’informations sur le gestionnaire de paramètres non valide, consultez Validation des paramètres.
État Comportement Valeur retournée errno Appelle un gestionnaire de paramètres non valide
Succès Écrit les caractères dans la mémoire tampon à l’aide de la chaîne de format spécifiée. Le nombre de caractères écrits, sans compter le caractère nul de fin. N/A Non
Erreur d’encodage lors du formatage Si le traitement du spécificateur sde chaîne , Sou Z, le traitement de la spécification de format s’arrête. -1 EILSEQ (42) Non
Erreur d’encodage lors du formatage Si vous traitez le spécificateur c de caractères ou C, le caractère non valide est ignoré. Le nombre de caractères écrits n’est pas incrémenté pour le caractère ignoré, et aucune donnée n’est écrite pour celui-ci. Le traitement de la spécification de format se poursuit après avoir sauté le spécificateur avec l’erreur d’encodage. Le nombre de caractères écrits, sans compter le NULL. EILSEQ (42) Non
buffer == NULL et count != 0 Si l’exécution se poursuit après l’exécution d’un gestionnaire de paramètres non valide, définit errno et renvoie une valeur négative. -1 EINVAL (22) Oui
buffer == NULL et count == 0 Aucune donnée n’est écrite Le nombre de caractères qui auraient été écrits, sans compter le NULL. Vous pouvez utiliser ce résultat pour allouer suffisamment d’espace tampon pour la chaîne et un NULL, puis appeler à nouveau la fonction pour remplir la mémoire tampon. N/A Non
count == 0 Aucune donnée n’est écrite -1 ERANGE (34) Non
count < 0 Non sécurisé : la valeur est traitée comme non signée, ce qui crée probablement une valeur importante qui entraîne l’écrasement de la mémoire qui suit la mémoire tampon. Le nombre de caractères écrits. N/A Non
count < sizeOfBuffer et len <= count Toutes les données sont écrites et une terminaison NULL est ajoutée. Le nombre de caractères écrits, sans compter le NULL. N/A Non
count < sizeOfBuffer et len > count Les premiers count-1 caractères sont écrits suivis d’un terminateur null. Le nombre de caractères qui auraient été écrits aurait count correspondu au nombre de caractères à afficher, sans compter le terminateur null. N/A Non
count >= sizeOfBuffer et len < sizeOfBuffer Toutes les données sont écrites avec un .NULL Le nombre de caractères écrits, sans compter le NULL. N/A Non
count >= sizeOfBuffer et len >= sizeOfBuffer Non sécurisé : écrase la mémoire qui suit la mémoire tampon. Le nombre de caractères écrits, sans compter le NULL. N/A Non
format == NULL Aucune donnée n’est écrite. Si l’exécution se poursuit après l’exécution d’un gestionnaire de paramètres non valide, définit errno et renvoie une valeur négative. -1 EINVAL (22) Oui

Pour plus d’informations sur ces codes d’erreur et d’autres, reportez-vous aux sections _doserrno, errno, _sys_errlistet _sys_nerr.

Mappages de routines de texte générique

Routine TCHAR.H _UNICODE et _MBCS non définis _MBCS défini _UNICODE défini
_vsntprintf _vsnprintf _vsnprintf _vsnwprintf
_vsntprintf_l _vsnprintf_l _vsnprintf_l _vsnwprintf_l

Spécifications

Routine En-tête obligatoire (C) En-tête obligatoire (C++)
vsnprintf, , _vsnprintf_vsnprintf_l <stdio.h> <stdio.h> ou <cstdio>
_vsnwprintf, _vsnwprintf_l <stdio.h> ou <wchar.h> <stdio.h>, <wchar.h>, <cstdio>ou <cwchar>

Les _vsnprintffonctions , _vsnprintf_l_vsnwprintfet _vsnwprintf_l sont spécifiques à Microsoft. Pour plus d’informations sur la compatibilité, consultez Compatibility.

Exemple : Utiliser des caractères larges avec _vsnwprintf()

// crt_vsnwprintf.c
// compile by using: cl /W3 crt_vsnwprintf.c

// To turn off error C4996, define this symbol:
#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <wtypes.h>

#define BUFFCOUNT (10)

void FormatOutput(LPCWSTR formatstring, ...)
{
    int nSize = 0;
    wchar_t buff[BUFFCOUNT];
    memset(buff, 0, sizeof(buff));
    va_list args;
    va_start(args, formatstring);
    // Note: _vsnwprintf is deprecated; consider vsnwprintf_s instead
    nSize = _vsnwprintf(buff, BUFFCOUNT - 1, formatstring, args); // C4996
    wprintf(L"nSize: %d, buff: %ls\n", nSize, buff);
    va_end(args);
}

int main() {
    FormatOutput(L"%ls %ls", L"Hi", L"there");
    FormatOutput(L"%ls %ls", L"Hi", L"there!");
    FormatOutput(L"%ls %ls", L"Hi", L"there!!");
}
nSize: 8, buff: Hi there
nSize: 9, buff: Hi there!
nSize: -1, buff: Hi there!

Le comportement change si vous utilisez vsnprintf à la place, ainsi que des paramètres de chaîne étroite. Le count paramètre peut correspondre à la taille totale de la mémoire tampon, et la valeur de retour est le nombre de caractères qui auraient été écrits s’il count avait été suffisamment grand :

Exemple : Utilisation vsnprintf() avec des cordes étroites

// crt_vsnprintf.c
// compile by using: cl /W4 crt_vsnprintf.c
#include <stdio.h>
#include <stdarg.h> // for va_list, va_start
#include <string.h> // for memset

#define BUFFCOUNT (10)

void FormatOutput(char* formatstring, ...)
{
    int nSize = 0;
    char buff[BUFFCOUNT];
    memset(buff, 0, sizeof(buff));
    va_list args;
    va_start(args, formatstring);
    nSize = vsnprintf(buff, sizeof(buff), formatstring, args);
    printf("nSize: %d, buff: %s\n", nSize, buff);
    va_end(args);
}

int main() {
    FormatOutput("%s %s", "Hi", "there");   //  8 chars + null
    FormatOutput("%s %s", "Hi", "there!");  //  9 chars + null
    FormatOutput("%s %s", "Hi", "there!!"); // 10 chars + null
}
nSize: 8, buff: Hi there
nSize: 9, buff: Hi there!
nSize: 10, buff: Hi there!

Voir aussi

E/S de flux
vprintf fonctions
Spécification de format, printf syntaxe : et wprintf fonctions
fprintf, , _fprintf_lfwprintf, ,_fwprintf_l
printf, , _printf_lwprintf, ,_wprintf_l
sprintf, _sprintf_l, , swprintf, _swprintf_l, __swprintf_l
va_arg, , va_copyva_end, ,va_start