I am writing a C program that is expected to be compiled with all major compilers. Currently I am developing on GCC on a linux machine and will compile on MSVC before committing the code. To make the cross-compiling easy, I am compiling with -ansi
and -pedantic
flags. This worked well until I started using snprintf
which is not available in C89 standard. GCC can compile this without the -ansi
switch but MSVC will fail always as it doesn't have C99 support.
So I did something like,
#ifdef WIN32
#define snprintf sprintf_s
#endif
This works well because snprintf
and sprintf_s
has same signatures. I am wondering is this the correct approach?
You could open the NUL special file for MSVC and write to that. It will always tell you how many bytes are needed, and won't write to anything. Like so:
You then should know how many bytes to allocate to use sprintf sucessfully.
Your proposal can work if you are being careful. The problem is that both function behave slightly different, if that is not a problem for you, you are good to go, otherwise think about a wrapper function:
Differences between MSVCs
_snprintf
and official C99 (gcc,clang)snprintf
:Return value:
Written bytes:
Interesting
%n
subtlety: If you use%n
in your code, MSVC will leave it unitialized! if it it stops parsing because buffer size is to small, GCC will always write number of bytes which would have been written if buffer would have been large enough.So my proposal would be to write your own wrapper function
mysnprintf
usingvsnprintf
/_vsnprintf
which gives same return values and writes the same bytes on both platforms (be careful:%n
is more difficult to fix).No. Your approach is doomed to failure.
sqrt
andcos
have the same prototype. Do you think you can swap them in a program and obtain the same behaviour from before / after the change?You probably should write your own
snprintf
, or download an implementation from the internet (google is your friend) and use that both in Linux and Windows.I found this on using
_snprintf()
as an alternative, and the gotchas involved if the buffer overrun protection actually triggers. From what I could see at a quick glance, similar caveats apply tosprintf_s
.Oh, and don't forget to send a mail to Microsoft demanding they support current language standards. (I know they already announced they have no plan to support C99, but bugger them anyway. They deserve it.)
Bottom line, if you want to play it really safe, you'll have to provide your own
snprintf()
(a wrapper around_snprintf()
orsprintf_s()
catching their non-standard behaviour) for MSVC.the most complete answer (you can improve if you wish), put that into a sticker