1

I'm trying to check address of member functions (dynamic, static and virtual) by following code. Since cout will convert such function address as bool type, so printf is used.

#include <iostream>
#include <stdio.h>
using namespace std;
class comple
{
public:
  void display () { cout << "comple: member" << endl; }
  static void display_s () { cout << "comple: static" << endl; }
  virtual void display_v () { cout << "comple: virtual" << endl; }
  int real, imag;
};

class B:public comple
{
public:
  virtual void display_v ();
};

void B::display_v () { cout << "B: virtual" << endl; }

int main () {
  printf ("1:comple: member=%p, \n", &comple::display);
  printf ("2:comple: static=%p, \n", &comple::display_s);
  printf ("3:comple: virtual=%p, \n", &comple::display_v);
  printf ("4:comple: member=%p, static=%p\n", &comple::display, &comple::display_s);
  printf ("5:comple: member=%p, virtual=%p\n", &comple::display, &comple::display_v);

  printf ("6:comple: member=%p, static=%p, virtual=%p\n", &comple::display, &comple::display_s, &comple::display_v);
  return 0;
}

Then outputs:

1:comple: member=0x400ae0, 
2:comple: static=0x400b0a, 
3:comple: virtual=0x1, 
4:comple: member=0x400ae0, static=(nil)
5:comple: member=0x400ae0, virtual=(nil)
6:comple: member=0x400ae0, static=(nil), virtual=0x400b0a

Outputs 1/2/3 seems OK, but static function address in output 4/6 is nil, which is supposed to have something, and virutal address of output 6 is actually static fucntion's address. Anyone can give a comment? thank you!

I'm using g++ version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).

========================================================================== I'd like to add some more details about assembly code of output 1/2/3 in C++ program above:

movq    $0, -248(%rbp)
movq    -256(%rbp), %rdx
movq    -248(%rbp), %rax
movq    %rdx, %rsi
movq    %rax, %rdx
movl    $.LC3, %edi
movl    $0, %eax
.cfi_offset 3, -24
call    printf  //printf ("1:comple: member=%p, \n", &comple::display);
movl    $_ZN6comple9display_sEv, %esi
movl    $.LC4, %edi
movl    $0, %eax
call    printf  //printf ("2:comple: static=%p, \n", &comple::display_s);
movq    $1, -240(%rbp)
movq    $0, -232(%rbp)
movq    -240(%rbp), %rdx
movq    -232(%rbp), %rax
movq    %rdx, %rsi
movq    %rax, %rdx
movl    $.LC5, %edi
movl    $0, %eax
call    printf    //printf ("3:comple: virtual=%p, \n", &comple::display_v);

In output 1/3, 2 64-bit words are used as arguments, while only 1 32-bit word is used for augument of output 2.

Yichen
  • 91
  • 1
  • 5
  • 3
    Fwiw, printing pointer-to-members via pointer mechanics of `printf` is non-standard because pointer-to-members aren't pointers. [Read this answer for more info](https://stackoverflow.com/a/14910723/1322972). – WhozCraig Jul 17 '17 at 08:13
  • 3
    [Duplicate?](https://stackoverflow.com/q/11111969/21567) – Christian.K Jul 17 '17 at 08:15
  • Thank you, WhozCraig. The strange behavior in assembly code is perhaps what you mean by "printf is non-standard". I'll look into C++ spec then. – Yichen Jul 17 '17 at 08:32
  • 2
    You cannot use `printf` to print values of any type not covered by the (finite) set of % conversions. Pointers to members are not covered. – n. m. could be an AI Jul 17 '17 at 08:36
  • 2
    Possible duplicate of [How to print member function address in C++](https://stackoverflow.com/questions/11111969/how-to-print-member-function-address-in-c) – TobiMcNamobi Jul 17 '17 at 11:12
  • Not a duplicate, as the linked question talks about `std::cout`. That is a much saner idea (`printf` comes from C which doesnt have member functions) but not even `std::cout` can print them. – MSalters Jul 17 '17 at 11:44
  • @MSalters The interesting part of the accepting answer is "In general, I think this means that it's impossible to print out the addresses of member functions without invoking undefined behavior". Duplicate or not - this answers the question above as well. – TobiMcNamobi Jul 18 '17 at 05:47

0 Answers0