pointer to member function difference ?

I have the following typdef :

typedef void (CCommandes::*LPFSMFUNC)(WORD idx, struct ParamQueue *pParam);

and the following line of code :

size_t typelen = sizeof( LPFSMFUNC );

The value of typelen is always "16" ...

Why not 4 ?

I try that code on 2 different machines ...

I have also :

LPFSMFUNC TabFunc ( 64 );

In MS VC 6.0 debugger Watch windows I can see :

 -[255] !!!

BOOL CGroupe::AddFunc (UINT key, LPFSMFUNC pfunc)
      if ((TabFunc[key] != NULL) || (key>MAXNFUNC))
            return FALSE;

      DWORD typelen = sizeof( LPFSMFUNC );
      return TRUE;

If key = 1 for example, in Watch window I can see:

 -[0] 0x00000000

 -[1] 0x00000000

 -[2] 0x00000000

 -[3] 0x00000000

 -[4] 0x004014ec CCommandes::GrpPrintShop_MPGetUser(WORD wThreadIdxParam, struct ParamQueue * pParam)


I know there is something wrong but I can't see what .

Thanks for helping me .

Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.


BTW, what happens when you change byte alignment options of your compiler (if possible)

bletualAuthor Commented:
Byte alignment to 1, 2, 4, 8 or 16 bytes didn't change
the result .

Well, I assume that the size also depends on the parameter list...
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Could you show us the class declaration for CCommandes?  Does that class have multiple inheritance?
bletualAuthor Commented:

the size do not depend on the parameter list

typedef void (CCommandes::*LPFSMFUNC2)(WORD idx, struct ParamQueue *pParam, struct ParamQueue *pParam2);

sizeof ( LPFSMFUNC2 ) return 16 also ...

bletualAuthor Commented:
class CCommandes

      // pParam->lpszPar[1]      Enter Date.
      // pParam->lpszPar[2]      Enter Time.

      // pParam->dwPar[0]            Full ID.
      // pParam->dwPar[1]            Pod Score.
      // pParam->dwPar[2]            Debriefing Score.
      // pParam->dwPar[3]            Minutes in Labyrinth.

      // pParam->iPar[0]            Nb of challenges.
      // pParam->iPar[1]            Nb of temples visited.
      // pParam->iPar[2]            Nb of correctly answered DB questions.
      // pParam->iPar[3]            Level of Debriefing questions (0-4).

      DWORD      m_dwFullID;
      char      m_Name[128];
      char      m_Firstname[128];
      char      m_Add1[128];
      char      m_Add2[128];
      char      m_City[128];
      char      m_State[128];
      char      m_Country[128];
      char      m_Zip[128];
      char      m_Email[128];
      char      m_Gender[128];
      DWORD      m_Age;
      char      m_Language[128];
      char      m_LastVisit[128];
      char      m_Friends[128];
      char      m_strDate[128];      
      char      m_strTime[128];
      char      m_strEndDate[128];
      char      m_strEndTime[128];
      char      m_strDbDate[128];            
      char      m_strDbTime[128];
      DWORD      m_nbPods;
      DWORD      m_PodScore;
      DWORD      m_DbScore;
      DWORD      m_DbLevel;                        ;

      char      m_strPodHisto[1024];
      char      m_strDebriefHisto[1024];

      // Recoit une commande "start"
      void CCommandes::GrpPrintShop_MPGetUser(WORD wThreadIdxParam, struct ParamQueue * pParam);
      void CCommandes::GrpPrintShop_MPGetHistory(WORD wThreadIdxParam, struct ParamQueue * pParam);
      void CCommandes::GrpPrintShop_PMGetUser(DWORD id);
      void CCommandes::GrpPrintShop_PMGetHistory(DWORD id);
      void CCommandes::GrpPrintShop_PMSetUser(char * lpszName, char * lpszFirstName,       char * lpszAdd1, char * lpszAdd2,
                                                                  char * lpszCity, char * lpszState,      char * lpszCountry, char * lpszZip,
                                                                  char * lpszEmail, char * lpszGender, char * lpszFriends, DWORD dwId,
                                                                  DWORD dwLanguage, DWORD dwAge);
      void CCommandes::GrpPrintShop_PMGetUserById(DWORD Fullid);
      void CCommandes::GrpPrintShop_MPStart(WORD wThreadIdxParam, struct ParamQueue * pParam);
Well that blows my theory.  I figured you probably had some multiple inheritance scheme, which makes the compiler store a pointer to the function and an offset so it can adjust the this pointer to point to an inherited base class.

I cut-and-pasted your class and compiled it here (Visual Studio 6.0 SP3), and I got 4 for my value of typelen.

If I do this:

class CFoo {};
Class CGoo {};
class CCommandes : public CGoo, public CFoo {

Then the value of typelen increases to 8.


Under Compiler Settings / Pointer-to-member representation, are you using "General Purpose Always"?

When I changed that, by typelen jumped to 16, just like yours.

Change that setting to "Best Case Always" and this might solve your problem.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
bletualAuthor Commented:
You show me the right way to heaven !

But the facts are :

If "Best Case Always"
 typelen = 16 .

If "General Purpose Always"
    "Point to Any Class *"
 typelen = 16 .
If "General Purpose Always"
    "Point to Single- and Multiple-Inheritance Classes"
 typelen = 8 .
If "General Purpose Always"
    "Point to Single- and Multiple-Inheritance Classes"
 typelen = 4 .

Do you have some explanations ?

I don't know the exact internal representation of how MSC++ does multiple inheritance, but it has something to do with storing offsets to the individual base classes of multiple inheritance.

For "General Purpose Always", the representation must assume that all classes use the worst-case representation that needs several offsets.  Probably for your simple class, all the offsets are always zero.

Now for your debugging example where it showed 256 elements in that function array, I have a feeling the Debugger doesn't handle that function array correctly -- it probably assumes (like most of us do) the function array is only an array of pointers, rather than a compilicated array of pointers and offsets.  So it thinks those offsets are extra elements in the array.

P.S. In your last comment, are the typelen values you indicate backwards?  I would think the "Best Case Always" would have a len=4 and "General Purpose Always" have a len=16.

bletualAuthor Commented:
If "Best Case Always"  typelen = 16 .

 If "General Purpose Always"
 "Point to Any Class *"
  typelen = 16 .
 If "General Purpose Always"
 "Point to Single- and Multiple-Inheritance Classes"
  typelen = 8 .
 If "General Purpose Always"
 "Point to Single- and Multiple-Inheritance Classes"
   typelen = 4 .

For me, the only case where typelen = 4 is the last one.

It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.