Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I print the address of a method pointer in C++?

Tags:

c++

For example:

struct A { void m() { } };

void stream_print() {
  void(A::*p)(void) = &A::m;
  std::cerr << p << std::endl;
}

void printf_print() {
  void(A::*p)(void) = &A::m;
  fprintf(stderr, "%p", p);
}

The stream_print() function always prints "1", which is obviously not what I want. The printf_print does not compile because p cannot be casted to void*.

What I need is a unique identifier for a method pointer that I can store in a container. I know this sounds like a bad idea, but I am developing a small toy for unit testing that can benefit from it. I am not worried about overloads of the method, I know how to get the pointer to a specific overload.

I am using g++ 4.4.3 with C++0x enabled.

Let me know if you have any doubts.

like image 912
Davi Avatar asked Mar 20 '11 06:03

Davi


People also ask

How do I find the address of a pointer?

To print the address of a variable, we use "%p" specifier in C programming language. There are two ways to get the address of the variable: By using "address of" (&) operator. By using pointer variable.

How do you print a pointer function?

There's no standard format specifier to print a function pointer. %p is only for data pointer, not for a function pointer. So to print a function pointer using %p is undefined behaviour. This works because converting any object to a character pointer is allowed ( char* , unsigned char* or signed char* ).

How do you get an address of a function?

We can get the address of a function by just writing the function's name without parentheses. Please refer function pointer in C for details. In C/C++, name of a function can be used to find address of function.

Which format modifier uses print the address of a pointer?

The line printf(“%d”,i) use the format specifier %d to print integers. In the next line %p is used to print addresses or pointer types in C.


2 Answers

Member function pointer is generally an object with non-trivial internal structure. Which is why you can't print it using tools intended for printing primitive types. Casting the pointer to void * is not a viable approach, since the size of member pointer is generally larger than sizeof(void *). Forcefully casting it to void * will in any case discard a portion of the pointer representation, thus no longer guaranteeing the uniqueness.

If what you are looking for is a unique string generated from the pointer, you can reinterpret the pointer as a character array, and use the string representation of character values in the identifier. Something like

void (A::*p)(void) = &A::m;

for (size_t i = 0; i < sizeof p; ++i)
  printf("%d ", reinterpret_cast<char *>(&p)[i]);

printf("\n");
like image 134
AnT Avatar answered Oct 02 '22 15:10

AnT


Though I'm not 100% sure I understand the question correctly, if some mapping from a member pointer to some unique id is needed, the following code might meet the purpose:

struct A {
  void f() {}
  void g( int ) {}
};

template< class T, T >
char* get_unique_id() {
  static char dummy;
  return &dummy;
}

int main() {
  set< char* >  s;
  s.insert( get_unique_id< decltype( &A::f ), &A::f >() );
  s.insert( get_unique_id< decltype( &A::g ), &A::g >() );
  s.insert( get_unique_id< decltype( &A::f ), &A::f >() );
  s.insert( get_unique_id< decltype( &A::g ), &A::g >() );
  cout<< s.size() <<endl; // prints 2
}

The call of get_unique_id is a little lengthy though...
Presumably some macro might help to make it simpler.

Hope this helps

like image 43
Ise Wisteria Avatar answered Oct 02 '22 17:10

Ise Wisteria