0

I have been reading a book about compiler and linker.The book give a demo about use the extern "C" to test the name mangling:

#include <stdio.h>

namespace myname{
    int var = 42;
}

extern "C" double _ZN6myname3varE;

int main(){
    printf("%d\n", _ZN6myname3varE);
    return 0;
}

The book tells that it will print 42 but I gets an error when compile it. I use:

g++ test_extern_c.cpp -o test_extern_c

and get:

test_extern_c.cpp:15:19: error: type mismatch with previous external decl of ‘double _ZN6myname3varE’ [-fpermissive]
 extern "C" double _ZN6myname3varE;
                   ^
test_extern_c.cpp:12:9: note: previous external decl of ‘int myname::var’
     int var = 42;
         ^
test_extern_c.cpp:15:19: error: redeclaration of ‘double _ZN6myname3varE’
 extern "C" double _ZN6myname3varE;
                   ^
test_extern_c.cpp:12:9: note: previous declaration ‘int myname::var’
     int var = 42;

So i wonder what happen.And I also change the type of the _ZN6myname3varE to int.And it will give the compiler error:

test_extern_c.cpp:15:16: error: redeclaration of ‘int _ZN6myname3varE’
 extern "C" int _ZN6myname3varE;
                ^
test_extern_c.cpp:12:9: note: previous declaration ‘int myname::var’
     int var = 42;

Is something different between my environment and the book's? Or may be the different version of g++ have different rule?

I have make some explorer:

  1. delete the code extern "C" double _ZN6myname3varE; and it can be compiled and the result is 42.
  2. move the code extern "C" double _ZN6myname3varE; to the top of namespace and change the type:

    #include <stdio.h>
    
    extern "C" int _ZN6myname3varE; 
    
    namespace myname{
        int var = 42;
    }
    
    //extern double _ZN6myname3varE;
    
    int main(){
        printf("%d\n", _ZN6myname3varE);
        return 0;
    }
    

and the result is 42 also.

jww
  • 97,681
  • 90
  • 411
  • 885
windyear
  • 15
  • 1
  • 4
  • 1
    `_ZN6myname3varE` is a reserved identifier. I'm pretty sure your code has undefined behavior. – melpomene Dec 08 '18 at 08:26
  • Highly bad stuff. If you want to extern C your code, no namespace, no class. What book? – Matthieu Brucher Dec 08 '18 at 08:38
  • The book's demo want to test the Name Decoration in gcc compiler.The Symbol _ZN6myname3varE is the Function Signature of the var in the namespace myname.@melpomene – windyear Dec 08 '18 at 08:51
  • @Matthieu Brucher It's a book written in Chinese.And I delete the the line of code:extern "C" double _ZN6myname3varE; And I got the result of 42. – windyear Dec 08 '18 at 08:52
  • 1
    Well, throw away the book :/ – Matthieu Brucher Dec 08 '18 at 08:54
  • Double looks wrong here: `double _ZN6myname3varE;`, but I think we need more context, like what the book actually said. Maybe the book is trying to place `int var` in the global namespace, and `double var` in the `myname` namespace to show they don't collide. – jww Dec 08 '18 at 10:23

3 Answers3

1

Keep in mind that name mangling is an implement-specific feature and is not defined by the C++ standard. So, not all C++ compilers would generate the same mangled name for the same declaration.

However, GNU compiler uses the IA64 ABI specification for name mangling. In that sense, your example, _ZN6myname3varE, is a mangled representation of myname::var, but the type is determined from the declaration, i.e., int for the former declaration of myname::var. And the compiler sees the latter as a re-declaration of the same name, which is prohibited.

Alirus
  • 472
  • 4
  • 14
  • It's not a redeclaration, it's an extern, a forward declaration. Perfectly fine to to forward declarations. – Matthieu Brucher Dec 08 '18 at 08:55
  • @MatthieuBrucher `extern "C"` highly differs from simply `extern`. You can see this [answer](https://stackoverflow.com/a/1041880/4614306) for more information. – Alirus Dec 08 '18 at 17:15
0

this seems to work:

#include <stdio.h>

namespace myname{
        extern int var;
}

extern "C" int _ZN6myname3varE = 42;

int main(){
        printf("%d\n", _ZN6myname3varE);
            return 0;
}

although there's still a complaint about using extern and initializng

arash kordi
  • 2,470
  • 1
  • 22
  • 24
  • I try this but an error is still happen.It means the redeclaration of the 'int _ZN6myname3varE'. The symbol _ZN6myname3varE is the Name Decoration of var in the namespace, so it's a redeclaration.Also ,I use the gcc compiler, other compiler may work. – windyear Dec 08 '18 at 11:39
0

change double to int, it can work.

[root@centos-test tmp]# cat t.cc
#include <stdio.h>

namespace myname{
    int var = 42;
}

extern "C" int _ZN6myname3varE;

int main(){
    printf("%d\n", _ZN6myname3varE);
    return 0;
}
[root@centos-test tmp]# ./t
42
[root@centos-test tmp]# 
xYZ
  • 107
  • 1
  • 9
  • What cpmpiler do you use?GCC?I try ths in my computer use gcc, and an error happen.error: redeclaration of ‘int _ZN6myname3varE’.IThe reason maybe the symbol of var is _ZN6myname3varE in the gcc standard. – windyear Dec 08 '18 at 11:33
  • @windyear g++ 4.8.5 – xYZ Dec 08 '18 at 11:38