vsnprintf, , _vsnprintf, _vsnprintf_l, , _vsnwprintf_vsnwprintf_l

Zapis sformatowanych danych wyjściowych przy użyciu wskaźnika do listy argumentów. Dostępne są bezpieczniejsze wersje tych funkcji; zobacz , , _vsnprintf_s, _vsnprintf_s_l, _vsnwprintf_s, _vsnwprintf_s_l.vsnprintf_s

Składnia

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

Parametry

buffer
Lokalizacja magazynu dla danych wyjściowych.

count
Maksymalna liczba znaków do zapisu. W przypadku funkcji, które przyjmują wchar_t, jest to liczba znaków szerokich do zapisania.

format
Specyfikacja formatu.

argptr
Wskaźnik do listy argumentów.

locale
Ustawienia regionalne do użycia.

Aby uzyskać więcej informacji, zobacz Składnia specyfikacji formatu.

Wartość zwracana

Liczba zapisanych znaków, a nie w tym zakończenie NULLlub wartość ujemna, jeśli wystąpi błąd wyjściowy.

Aby uzyskać szczegółowe informacje, zobacz Podsumowanie zachowania.

Uwagi

Każda z tych funkcji przyjmuje wskaźnik do listy argumentów, a następnie formatuje dane i zapisuje maksymalnie count znaki do pamięci wskazywanej przez bufferwartość . Funkcja vsnprintf zawsze zapisuje terminator o wartości null, nawet jeśli obcina dane wyjściowe. Jeśli używasz _vsnprintf wartości i _vsnwprintf, bufor jest zakończony wartością null tylko wtedy, gdy na końcu znajduje się miejsce (czyli jeśli liczba znaków do zapisania jest mniejsza niż count).

Począwszy od UCRT w programach Visual Studio 2015 i Windows 10, vsnprintf nie jest już identyczny z _vsnprintf. Funkcja vsnprintf jest zgodna ze standardem C99; _vsnprintf jest zachowana w celu zapewnienia zgodności z poprzednim kodem. Różnica polega na tym, że jeśli zabraknie buforu, vsnprintf wartość null kończy koniec buforu i zwraca liczbę znaków, które byłyby wymagane, podczas gdy _vsnprintf bufor nie kończy się wartością null i zwraca wartość -1. Ponadto zawiera jeszcze jeden znak w danych wyjściowych, _vsnprintf() ponieważ nie powoduje zakończenia buforu o wartości null.

Ważne

Aby zapobiec pewnym rodzajom zagrożeń bezpieczeństwa, upewnij się, że format nie jest to ciąg zdefiniowany przez użytkownika. Aby uzyskać więcej informacji, zobacz Unikanie przekroków buforu. Począwszy od systemu Windows 10 w wersji 2004 (kompilacja 19041), printf rodzina funkcji drukuje dokładnie możliwe liczby zmiennoprzecinkowe zgodnie z regułami IEEE 754 dotyczącymi zaokrąglania. W poprzednich wersjach systemu Windows dokładnie reprezentowane liczby zmiennoprzecinkowe kończące się na "5" zawsze zaokrągla się w górę. IEEE 754 stwierdza, że muszą zaokrąglić do najbliższej parzysta cyfra (znana również jako "Zaokrąglanie Bankiera"). Na przykład oba printf("%1.0f", 1.5)printf("%1.0f", 2.5) elementy i powinny być zaokrąglone do 2. Wcześniej 1,5 zaokrągliłoby się do 2 i 2,5 do 3. Ta zmiana dotyczy tylko dokładnie możliwych do reprezentowania liczb. Na przykład 2,35 (który, gdy jest reprezentowany w pamięci, jest bliżej 2,350000000000000008) nadal zaokrągla się do 2,4. Zaokrąglanie wykonywane przez te funkcje jest teraz również zgodne z trybem zaokrąglania zmiennoprzecinkowego ustawionym przez fesetround. Wcześniej zaokrąglanie zawsze wybierało FE_TONEAREST zachowanie. Ta zmiana dotyczy tylko programów utworzonych przy użyciu programu Visual Studio 2019 w wersji 16.2 lub nowszej. Aby użyć starszego zachowania zaokrąglania zmiennoprzecinkowego, połącz się z elementem "legacy_stdio_float_rounding.obj".

Uwaga

Aby upewnić się, że istnieje miejsce na zakończenie wartości null podczas wywoływania _vsnprintfparametrów , _vsnprintf_l_vsnwprintf i _vsnwprintf_l, upewnij się, że count długość buforu jest ściśle mniejsza niż długość buforu i zainicjuj bufor do wartości null przed wywołaniem funkcji.

Ponieważ vsnprintf zawsze zapisuje wartość null zakończenia, count parametr może być równy rozmiarowi buforu.

Wersje tych funkcji z sufiksem _l są identyczne, z tą różnicą, że używają parametru ustawień regionalnych przekazanych zamiast bieżących ustawień regionalnych wątku.

W języku C++te funkcje mają przeciążenia szablonu, które wywołują nowsze, bezpieczne odpowiedniki tych funkcji. Aby uzyskać więcej informacji, zobacz Bezpieczne przeciążenia szablonów.

Podsumowanie zachowania

W poniższej tabeli:

  • Niech sizeOfBuffer będzie rozmiar .buffer Jeśli funkcja przyjmuje char bufor, rozmiar jest w bajtach. Jeśli funkcja przyjmuje wchar_t bufor, rozmiar określa liczbę 16-bitowych wyrazów.
  • Pozwól len na rozmiar sformatowanych danych. Jeśli funkcja przyjmuje char bufor, rozmiar jest w bajtach. Jeśli funkcja przyjmuje wchar_t bufor, rozmiar określa liczbę 16-bitowych wyrazów.
  • Znaki odwołują się do char znaków funkcji, które przyjmują char bufor, oraz do wchar_t znaków funkcji, które przyjmują wchar_t bufor.
  • Aby uzyskać więcej informacji na temat nieprawidłowej procedury obsługi parametrów, zobacz Walidacja parametrów.
Stan Zachowanie Wartość zwracana errno Wywołuje nieprawidłową procedurę obsługi parametrów
Powodzenie Zapisuje znaki w buforze przy użyciu określonego ciągu formatu. Liczba zapisanych znaków, bez zliczania znaku null zakończenia. Nie dotyczy Nie.
Błąd kodowania podczas formatowania Jeśli przetwarzanie specyfikatora sciągów , Slub Z, przetwarzanie specyfikacji formatu zatrzymuje się. -1 EILSEQ (42) Nie.
Błąd kodowania podczas formatowania Jeśli specyfikator c znaków przetwarzania lub C, jest pomijany nieprawidłowy znak. Liczba zapisanych znaków nie jest zwiększana dla pominiętego znaku ani żadnych zapisanych dla niego danych. Przetwarzanie specyfikacji formatu jest kontynuowane po pomijaniu specyfikatora z błędem kodowania. Liczba zapisanych znaków, a nie łącznie z kończeniem NULL. EILSEQ (42) Nie.
buffer == NULL i count != 0 Jeśli wykonanie będzie kontynuowane po wykonaniu nieprawidłowego programu obsługi parametrów, ustawia errno i zwraca wartość ujemną. -1 EINVAL (22) Tak
count == 0 Żadne dane nie są zapisywane Liczba znaków, które zostałyby zapisane, a nie łącznie z kończeniem NULL. Możesz użyć tego wyniku, aby przydzielić wystarczającą ilość miejsca buforu dla ciągu i zakończenia NULL, a następnie wywołać funkcję ponownie, aby wypełnić bufor. Nie dotyczy Nie.
count < 0 Niebezpieczne: wartość jest traktowana jako niepodpisane, prawdopodobnie tworząc dużą wartość, która powoduje zastąpienie pamięci, która następuje po buforze. Liczba zapisanych znaków. Nie dotyczy Nie.
count < sizeOfBuffer i len <= count Wszystkie dane są zapisywane i dołączane są kończenie NULL . Liczba zapisanych znaków, a nie łącznie z kończeniem NULL. Nie dotyczy Nie.
count < sizeOfBuffer i len > count count-1 Pierwsze znaki są zapisywane, a następnie terminator o wartości null. Liczba zapisanych znaków count była zgodna z liczbą znaków w danych wyjściowych, a nie w tym terminatorem o wartości null. Nie dotyczy Nie.
count >= sizeOfBuffer i len < sizeOfBuffer Wszystkie dane są zapisywane z kończeniem NULL. Liczba zapisanych znaków, a nie łącznie z kończeniem NULL. Nie dotyczy Nie.
count >= sizeOfBuffer i len >= sizeOfBuffer Niebezpieczne: zastępuje pamięć, która następuje po buforze. Liczba zapisanych znaków, a nie łącznie z kończeniem NULL. Nie dotyczy Nie.
format == NULL Żadne dane nie są zapisywane. Jeśli wykonanie będzie kontynuowane po wykonaniu nieprawidłowego programu obsługi parametrów, ustawia errno i zwraca wartość ujemną. -1 EINVAL (22) Tak

Aby uzyskać informacje o tych i innych kodach błędów, zobacz _doserrno, errno, _sys_errlisti _sys_nerr.

Mapowania procedur tekstu ogólnego

TCHAR.H Rutynowych _UNICODE i _MBCS niezdefiniowane _MBCS Zdefiniowane _UNICODE Zdefiniowane
_vsntprintf _vsnprintf _vsnprintf _vsnwprintf
_vsntprintf_l _vsnprintf_l _vsnprintf_l _vsnwprintf_l

Wymagania

Procedura Wymagany nagłówek (C) Wymagany nagłówek (C++)
vsnprintf, , _vsnprintf_vsnprintf_l <stdio.h> <stdio.h> lub <cstdio>
_vsnwprintf, _vsnwprintf_l <stdio.h> lub <wchar.h> <stdio.h>, <wchar.h>, lub <cstdio><cwchar>

Funkcje _vsnprintf, _vsnprintf_l_vsnwprintf i _vsnwprintf_l są specyficzne dla firmy Microsoft. Aby uzyskać więcej informacji o zgodności, zobacz Zgodność.

Przykład: używanie znaków szerokich z _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!

Zachowanie zmienia się, jeśli zamiast tego używasz vsnprintf wraz z parametrami wąskich ciągów. Parametr count może być całym rozmiarem buforu, a zwracana wartość to liczba znaków, które zostałyby zapisane, gdyby count były wystarczająco duże:

Przykład: użyj z vsnprintf() wąskimi ciągami

// 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!

Zobacz też

We/Wy strumienia
vprintf, funkcje
Składnia specyfikacji formatu: printf i wprintf funkcje
fprintf, , _fprintf_l, , fwprintf_fwprintf_l
printf, , _printf_l, , wprintf_wprintf_l
sprintf, , _sprintf_l, swprintf, , _swprintf_l__swprintf_l
va_arg, , va_copy, , va_endva_start