Name Mangling in C ++

I was looking through an article - http://www.geeksforgeeks.org/extern-c-in-c/

There are two examples -

int printf(const char *format,...); int main() { printf("GeeksforGeeks"); return 0; } 

They say that this will not compile, because the compiler will not be able to find the desired version of the 'printf' function. However, below are the results.

 extern "C" { int printf(const char *format,...); } int main() { printf("GeeksforGeeks"); return 0; } 

This beacuse extern block "C" prevents name distortion. However, code execution and data output. Where does he get the definition of "printf". I read a post saying that "stdio.h" is enabled by default. If so, the code below should be executed. However, it gives an error that printf is not defined.

 int main() { printf("GeeksforGeeks"); return 0; } 

Can someone explain this?

+6
source share
2 answers

Your compiler is useful, treating printf specifically as inline.

Example 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 the Microsoft cl compiler command "cl / c tst.cpp", we can check 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 garbled.

But when we compile with / usr / lib / gcc / i 686-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 distorted, but printf () is not, because the cygwin compiler is useful. Most of them consider this to be a compiler defect. If the cygwin compiler is called using "g ++ -fno-builtin -c tst.cpp", the problem disappears and both characters are garbled, as it should be.

The more current g ++ is correct, with compilation with / usr / libexec / gcc / i 686-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 garbled.

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 distorted:

 00000000 b .bss 00000000 d .data 00000000 r .rdata 00000000 t .text U __Z3fooiPKc U __Z6printfPKcz U ___main U __alloca 00000000 T _main 
+4
source

Let's look at the corresponding standard quotes:

17.6.2.3 Communication [using.linkage]

2 If the name from the C standard library declared with external link has extern "C" or extern "C++" , the reference is determined by the implementation. For this purpose, it is recommended that you use the extern "C++" link for this purpose.

17.6.4.3 Reserved Names [reserved.names]

2 If a program declares or defines a name in the context where it is reserved, except as explicitly permitted by this section, its behavior is undefined.

17.6.4.3.3 External Relationship [extern.names]

1 Each name declared as an object with an external link in the header is reserved for implementation to assign this library object with an external link, both in the std namespace and in the global namespace.
2 Each global function signature declared with an external link in the header is reserved for implementation to assign this signature to an external link function.
3 Each name from the Standard C library declared with external link is reserved for implementation for use as a name with extern "C" linkage, both in the std namespace and in the global namespace. 4 Each function signature from the Standard C library declared with external binding is reserved for implementation for use as a function signature with the extern "C" and extern "C++" or as the namespace namespace in the global namespace.

What we get from this is that the compiler can assume that printf in any of these instances always refers to the standard library function printf and, therefore, can have any information about their baking. And if you are mistaken in the declaration or simply provide your own, she can do whatever she wants, including, but not limited to, a magical correction. In any case, you cannot know what language connection he expects.

+1
source

All Articles