How to print function pointers with cout?

前端 未结 7 2427
挽巷
挽巷 2020-11-22 07:09

I want to print out a function pointer using cout, and found it did not work. But it worked after I converting the function pointer to (void *), so does printf with %p, such

相关标签:
7条回答
  • 2020-11-22 07:09

    Regarding your edit, you can print out contents of anything by accessing it via unsigned char pointer. An example for pointers to member functions:

    #include <iostream>
    #include <iomanip>
    
    struct foo { virtual void bar(){} };
    struct foo2 { };
    struct foo3 : foo2, foo { virtual void bar(){} };
    
    int main()
    {
        void (foo3::*p)() = &foo::bar;
    
        unsigned char const * first = reinterpret_cast<unsigned char *>(&p);
        unsigned char const * last = reinterpret_cast<unsigned char *>(&p + 1);
    
        for (; first != last; ++first)
        {
            std::cout << std::hex << std::setw(2) << std::setfill('0')
                << (int)*first << ' ';
        }
        std::cout << std::endl;
    }
    
    0 讨论(0)
  • 2020-11-22 07:20

    There actually is an overload of the << operator that looks something like:

    ostream & operator <<( ostream &, const void * );
    

    which does what you expect - outputs in hex. There can be no such standard library overload for function pointers, because there are infinite number of types of them. So the pointer gets converted to another type, which in this case seems to be a bool - I can't offhand remember the rules for this.

    Edit: The C++ Standard specifies:

    4.12 Boolean conversions

    1 An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool.

    This is the only conversion specified for function pointers.

    0 讨论(0)
  • 2020-11-22 07:21

    maybe (in one time I stay intersecting about the address of function) one of decision )))

    #include <iostream>     
    #include <stdlib.h>
    
    void alexf();
    
    int main()
    { 
        int int_output;
    
        printf("printf(\"%%p\", pf) is %p\n", alexf);
    
        asm( "movl %[input], %%eax\n"                
             "movl %%eax, %[output]\n" 
             : [output] "+m" (int_output)
             : [input] "r" (&alexf)
             : "eax", "ebx"
        );
    
            std::cout<<"" <<std::hex<<int_output <<""<<std::endl;
        return 0;
    }
    
    void  alexf() {  }
    

    passing the pointer to function (&alexf) or other pointer using & use constraint r. Let gcc to use register for input argument)).

    0 讨论(0)
  • 2020-11-22 07:22

    In C++11 one could modify this behavior by defining a variadic template overload of operator<< (whether that is recommendable or not is another topic):

    #include<iostream>
    namespace function_display{
    template<class Ret, class... Args>
    std::ostream& operator <<(std::ostream& os, Ret(*p)(Args...) ){ // star * is optional
        return os << "funptr " << (void*)p;
    }
    }
    
    // example code:
    void fun_void_void(){};
    void fun_void_double(double d){};
    double fun_double_double(double d){return d;}
    
    int main(){
        using namespace function_display;
        // ampersands & are optional
        std::cout << "1. " << &fun_void_void << std::endl; // prints "1. funptr 0x40cb58"
        std::cout << "2. " << &fun_void_double << std::endl; // prints "2. funptr 0x40cb5e"
        std::cout << "3. " << &fun_double_double << std::endl; // prints "3. funptr 0x40cb69"
    }
    
    0 讨论(0)
  • 2020-11-22 07:31

    Regarding your specific question,

    how can we observe the content of a member function pointers?

    The answer is, other than converting them to bool to express that it points to something or it doesn't, you can't 'observer' member function pointers. At least not in a compliant way. The reason is because the standard explicitly disallows this:

    4.12 footnote 57:

    57) The rule for conversion of pointers to members (from pointer to member of base to pointer to member of derived) appears inverted compared to the rule for pointers to objects (from pointer to derived to pointer to base) (4.10, clause 10). This inversion is necessary to ensure type safety. Note that a pointer to member is not a pointer to object or a pointer to function and the rules for conversions of such pointers do not apply to pointers to members. In particular, a pointer to member cannot be converted to a void*.

    For example, here is sample code:

    #include <cstdlib>
    #include <vector>
    #include <algorithm>
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Gizmo
    {
    public:
        void DoTheThing()
        {
            return;
        };
    
    
    private:
        int foo_;
    };
    
    int main()
    {
        void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
    
        Gizmo g;
        (g.*fn)();  // once you have the function pointer, you can call the function this way
    
        bool b = fn;
    //  void* v = (void*)fn;    // standard explicitly disallows this conversion
        cout << hex << fn;
        return 0;
    }
    

    I note that my debugger (MSVC9) is able to tell me the actual physical address of the member function at runtime, so I know there must be some way to actually get that address. But I'm sure it is non-conformant, non-portable and probably involves machine code. If I were to go down that road, I would start by taking the address of the function pointer (eg &fn), casting that to void*, and go from there. This would also require you know the size of pointers (different on different platforms).

    But I would ask, so long as you can convert the member-function pointer to bool and evaluate the existance of the pointer, why in real code would you need the address?

    Presumably the answer to the last question is "so I can determine if one function pointer points to the same function as another." Fair enough. You can compare function pointers for equality:

    #include <cstdlib>
    #include <vector>
    #include <algorithm>
    #include <string>
    #include <iostream>
    using namespace std;
    
    class Gizmo
    {
    public:
        void DoTheThing()
        {
            return;
        };
    
        **void DoTheOtherThing()
        {
            return;
        };**
    
    
    private:
        int foo_;
    };
    
    int main()
    {
        void(Gizmo::*fn)(void) = &Gizmo::DoTheThing;
    
        Gizmo g;
        (g.*fn)();  // once you have the function pointer, you can call the function this way
    
        bool b = fn;
    //  void* v = (void*)fn;    // standard explicitly disallows this conversion
        cout << hex << fn;
    
        **void(Gizmo::*fnOther)(void) = &Gizmo::DoTheOtherThing;
    
        bool same = fnOther == fn;
        bool sameIsSame = fn == fn;**
    
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 07:32

    Casting pointers to (void*) to print them to cout is the right thing (TM) to do in C++ if you want to see their values.

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