Your compiler is being helpful by treating printf specially as a built-in.
Sample code "tst.cpp":
int printf(char const *format,...);
int foo(int a, char const *b);
int main() {
printf("Hello, World!");
foo(42, static_cast<char const *>("Hello, World!"));
return 0;
}
When compiling with Microsoft's cl compiler command "cl /c tst.cpp" we can inspect the resulting .obj and find:
00000000 r $SG2552
00000010 r $SG2554
00000000 N .debug$S
00000000 i .drectve
00000000 r .rdata
00000000 t .text$mn
U ?foo@@YAHHPBD@Z
U ?printf@@YAHPBDZZ
00e1520d a @comp.id
80000191 a @feat.00
00000000 T _main
Note that both foo() and printf() are mangled.
But when we compile with /usr/lib/gcc/i686-pc-cygwin/3.4.4/cc1plus.exe via cygwin "g++ -c tst.cpp", we get:
00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
U __Z3fooiPKc
U ___main
U __alloca
00000000 T _main
U _printf
Here foo() is mangled and printf() is not, because the cygwin compiler is being helpful. Most would consider this a compiler defect. If the cygwin compiler is invoked with "g++ -fno-builtin -c tst.cpp" then the problem goes away and both symbols are mangled as they should be.
A more up-to-date g++ gets it right, compiling with with /usr/libexec/gcc/i686-redhat-linux/4.8.3/cc1plus via "g++ -c tst.cpp" we get:
00000000 T main
U _Z3fooiPKc
U _Z6printfPKcz
Both foo() and printf() are mangled.
But if we declare printf such that cygwin g++ does not recognize it:
char const * printf(char const *format,...);
int foo(int a, char const *b);
int main() {
printf("Hello, World!");
foo(42, static_cast<char const *>("Hello, World!"));
return 0;
}
Then both foo() and printf() are mangled:
00000000 b .bss
00000000 d .data
00000000 r .rdata
00000000 t .text
U __Z3fooiPKc
U __Z6printfPKcz
U ___main
U __alloca
00000000 T _main