I'm working with a C codebase in which my predecessor used:
#ifdef _MSC_VER
// Map to equivalent function
#define snprintf sprintf_s
#endif
The codebase needs to compile on Linux (gcc/clang), OSX (gcc/clang) and Windows (VS). I've attempted to compile the code in Visual Studio 2015 for the first time. Previously Visual Studio 2010 had been used. I encountered the error described here and was able to compile using a clue from the accepted answer:
#ifdef _MSC_VER
#if _MSC_VER<1900
#define snprintf sprintf_s
#endif
#endif
The project compiles now with Visual Studio 2015 and clang on OSX. However, I'm concerned about a statement in the sprintf_s documentation:
Unlike snprintf, sprintf_s guarantees that the buffer will be null-terminated (unless the buffer size is zero).
If Visual Studio is including a C99 compliant version of snprintf
, shouldn't the buffer be guaranteed to be null-terminated?
I wrote a small program to evaluate the behavior.
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
char buf[5];
snprintf(buf, sizeof(buf), "abcdef");
printf("buffer: %s\n", buf);
printf("size of buffer: %lu\n", strlen(buf));
printf("last character a null terminator?: %s\n",
(strcmp(&buf[4], "\0") == 0) ? "yes" : "no");
return 0;
}
I built and ran the program on OSX, and Windows with Visual Studio 2015.
On OSX, the output is:
~$c99 main.c
~$./a.out
buffer: abcd
size of buffer: 4
last character a null terminator?: yes
On Windows 7 with Visual Studio 2015 the output is
> printf_evaluation.exe
buffer: abcd
size of buffer: 4
last character a null terminator?: yes
Doesn't that demonstrate the the output is in fact null-terminated, and suggest that the MSDN documentation is incorrect? Is my example too trivial? Are there cases when the output of snprintf
might not be NULL terminated with Visual Studio 2015?