Link error with really simple functions C++ on .h file

后端 未结 4 1022
离开以前
离开以前 2021-01-05 19:09

I\'ve made two functions to \'cast\' a 32/64 bit pointer into a double. The code worked when used alone (Just the .h and a .cpp including it) but when using the .h somewhere

相关标签:
4条回答
  • 2021-01-05 19:22

    You get the error because the functions are compiled twice (each time the header is included), and so the linker, which combines all the object files into the final executable, sees multiple definitions of the functions.

    Like Armen wrote, one solution is to make the functions inline. This way the code for the functions is always copied whenever they are used. This is a feasible solution here because the functions are so small that the code won't get very bloated. If you have any larger functions in a header file or you need to organize your code better, you should take the code from the header file and put in in a cpp file (like in sehe's answer).

    0 讨论(0)
  • 2021-01-05 19:25

    Mark your functions inline

    inline double ptr2double(void* pv){
        ptr_u ptr;
        ptr.p = pv;
        return (ptr.d);
    };
    
    inline void* double2ptr(double dv){
        ptr_u ptr;
        ptr.d = dv;
        return(ptr.p);
    };
    

    You see, when you included the same function in two separate source files (translation units), you get multiple definitions. You have generally 2 options:

    • Have delrarations of your funcions in a .h file, and definitions in a separate .cpp file
    • Make your functions inline and keep them in a .h file

    The One-Definition Rule of C++ prohibits multiple definitions of non-inline functions.

    EDIT: The #ifdef guards guard against multiple inclusion into a single source file. But you can indeed include the .h file into different .cpp files. The ODR applies to definitions in the whole program, not just a single file.

    EDIT2 After some comments I feel like I must incorporate this piece of information here lest there should be any misunderstanding. In C++ there are different rules concerning inline functions and non-inline ones, for example the special case of ODR. Now, you may mark any function (be it long or recursive, doesn't matter) as inline, and the special rules will apply to them. It is a completely different matter whether the compiler will decide to actually inline it (that is, substitute the code instead of a call), which it can do even if you don't mark the function as inline, and can decide not to do even if you mark it as inline.

    0 讨论(0)
  • 2021-01-05 19:30

    The canonical way to would be:

    floatcast.h

    #pragma once
    #ifndef __FLOATCAST_H
    #define __FLOATCAST_H
    
    //A quick and dirty way of casting pointers into doubles and back
    //Should work with BOTH 64bit and 32bit pointers
    union ptr_u {
        double d;
        void* p;
    };
    
    double ptr2double(void* pv);
    void* double2ptr(double dv);
    
    #endif
    

    floatcast.cpp

    #include "floatcast.h"
    
    double ptr2double(void* pv){
        ptr_u ptr;
        ptr.p = pv;
        return (ptr.d);
    };
    
    void* double2ptr(double dv){
        ptr_u ptr;
        ptr.d = dv;
        return(ptr.p);
    };    
    
    0 讨论(0)
  • 2021-01-05 19:31

    Put your code in a .cpp file and in the .h file just put the prototypes -

    double ptr2double(void* pv);
    void* double2ptr(double dv);
    

    Or keep the code as it is and add "inline" to each function definition which will allow you to define them in each module

    Although I don't think that your code will actually do anything very useful. it's undefined behavour to access a different member of a union than the one you used to store the data. Plus even if that "worked" I can't think how you plan to use this, you'll store a double and read 32 bits of it into a pointer (on a 32 bit machine)... How can you possibly make use of this for anything?

    0 讨论(0)
提交回复
热议问题