102 votes

snprintf et Visual Studio 2010

J'ai la malchance de devoir utiliser VS 2010 pour un projet, et j'ai remarqué que le code suivant ne se construit toujours pas en utilisant le compilateur non conforme aux normes :

#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    char buffer[512];

    snprintf(buffer, sizeof(buffer), "SomeString");

    return 0;
}

(la compilation échoue avec l'erreur : C3861 : 'snprintf' : identifiant non trouvé)

Je me souviens que c'était déjà le cas avec VS 2005 et je suis choqué de voir que cela n'a toujours pas été corrigé.

Quelqu'un sait-il si Microsoft a l'intention de faire passer ses bibliothèques C standard en 2010 ?

88voto

Valentin Milea Points 781

Histoire courte : Microsoft a enfin implémenté snprintf dans Visual Studio 2015. Sur les versions antérieures, vous pouvez le simuler comme ci-dessous.


Version longue :

Voici le comportement attendu de snprintf :

int snprintf( char* buffer, std::size_t buf_size, const char* format, ... );

Écrit au maximum buf_size - 1 caractères dans une mémoire tampon. La chaîne de caractères La chaîne de caractères résultante sera terminée par un ch buf_size est égal à zéro. Si buf_size est égal à zéro, rien n'est écrit buffer peut être un pointeur nul. La valeur de retour est le nombre de caractères qui auraient été écrits dans l'hypothèse d'une buf_size , sans compter le caractère nul de fin.

Les versions antérieures à Visual Studio 2015 ne disposaient pas d'une implémentation conforme. Il existe à la place des extensions non standard telles que _snprintf() (qui n'écrit pas de terminateur nul en cas de dépassement de capacité) et _snprintf_s() (qui peut appliquer la terminaison nulle, mais renvoie -1 en cas de débordement au lieu du nombre de caractères qui auraient été écrits).

Solution de repli suggérée pour VS 2005 et les versions ultérieures :

#if defined(_MSC_VER) && _MSC_VER < 1900

#define snprintf c99_snprintf
#define vsnprintf c99_vsnprintf

__inline int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap)
{
    int count = -1;

    if (size != 0)
        count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
    if (count == -1)
        count = _vscprintf(format, ap);

    return count;
}

__inline int c99_snprintf(char *outBuf, size_t size, const char *format, ...)
{
    int count;
    va_list ap;

    va_start(ap, format);
    count = c99_vsnprintf(outBuf, size, format, ap);
    va_end(ap);

    return count;
}

#endif

33voto

KennyTM Points 232647

snprintf ne fait pas partie du C89. Il n'est standard que dans le C99. Microsoft a pas de plan de soutien au C99 .

(Mais c'est aussi la norme en C++0x... !)

Voir les autres réponses ci-dessous pour une solution de contournement.

8voto

Quandary Points 12867

Si vous n'avez pas besoin de la valeur de retour, vous pouvez également définir snprintf comme _snprintf_s

#define snprintf(buf,len, format,...) _snprintf_s(buf, len,len, format, __VA_ARGS__)

3voto

Il-Bhima Points 5757

Je crois que l'équivalent pour Windows est sprintf_s

2voto

Marco Pracucci Points 81

Un autre remplacement sûr de snprintf() y vsnprintf() est fournie par ffmpeg. Vous pouvez consulter la page source ici (suggéré).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X