libstdc++ does define __USE_MINGW_ANSI_STDIO
during build (config/os/mingw32-w64/os_defines.h
), which will turn on the mingw sprintf
wrapper. As @Michael Burr pointed out, these wrappers exist for C99/GNU99 compatibility.
Your test does not define __USE_MINGW_ANSI_STDIO
, hence you'll not get the wrapper with stdio.h
. But since it was defined when building libstdc++, you'll get it with cstdio
.
If you however define it yourself before including stdio.h
, you will get the wrapper again.
So you do get in fact different implementations, and cstdio std::sprintf
is not necessarily the same as stdio.h sprintf
, at least not when it comes to mingw.
Here is a test. First the source:
#ifdef USE_STDIO
#include <stdio.h>
#else
#include <cstdio>
using std::sprintf;
#endif
int main () {
int i;
for (i = 0; i < 500000; i++){
char x[100];
sprintf(x, "x%dx%dx", i, i<<2);
}
}
Results:
$ g++ -o test_cstdio.exe test.cc
$ g++ -o test_stdio.exe -DUSE_STDIO test.cc
$ g++ -o test_stdio_wrap.exe -DUSE_STDIO -D__USE_MINGW_ANSI_STDIO test.cc
$ for x in test_*.exe; do ( echo $x; objdump -d $x | grep sprintf; echo ); done
test_cstdio.exe
40154a: e8 41 64 00 00 callq 407990 <_Z7sprintfPcPKcz>
0000000000402c40 <__mingw_vsprintf>:
0000000000407990 <_Z7sprintfPcPKcz>:
4079c8: e8 73 b2 ff ff callq 402c40 <__mingw_vsprintf>
test_stdio.exe
40154a: e8 71 62 00 00 callq 4077c0 <sprintf>
00000000004077c0 <sprintf>:
4077c0: ff 25 6e 6c 00 00 jmpq *0x6c6e(%rip) # 40e434 <__imp_sprintf>
test_stdio_wrap.exe
40154a: e8 41 64 00 00 callq 407990 <_Z7sprintfPcPKcz>
0000000000402c40 <__mingw_vsprintf>:
0000000000407990 <_Z7sprintfPcPKcz>:
4079c8: e8 73 b2 ff ff callq 402c40 <__mingw_vsprintf>