How to get address of some struct member in array

2019-08-30 07:01发布

问题:

I try to get the address of some struct member in array of structures but i don't want to use name of that member.

It should be something like this:

typedef struct{               
  unsigned char MrChar;
  unsigned short MrShort;
  unsigned long MrLong;
  unsigned char MrArray[5];
}tModule;

static tModule taModulesArray[MODULES_AMOUNT] = {  // MODULES_AMOUNT = 2
  {0x22, 0x3298, 0x92324583, "djsoe"}, // Module 1
  {0x33, 0x1843, 0x65644113, "gskwc"}, // Module 2  
};

unsigned long usGetMemberAddr(unsigned long ulModule, unsigned long ulMember){
  unsigned long Address;
  Address = abs(taModulesArray_BaseAddress - taModulesArray[ulModule].[ulMember]);
  return Address;
}

I need that for quick modification of configuration (in EEPROM) which is in different structs. So I try to do function which takes number of module and index of one of the module member and returns offset of for proper member.

If there is any possibility for something like that line before return?

回答1:

We can use the below logic also to find the offset of each memebers of a structure and then we can directly add it to the base addres of the particular instance of the structure variable.

#define OFFSET(type, member)   ( (int) (& ( ((type *)(0))->member ) ) )

int find_offset(unsigned long ulMember)
{
    unsigned long off = 0;

    switch(ulMember)
    {
         case 1:
             off = OFFSET(tModule, MrChar);
             break;
         case 2:
             off = OFFSET(tModule, MrShorc);
             break;
         case 3:
             off = OFFSET(tModule, MrLong);
             break;
         case 4:
             off = OFFSET(tModule, MrArray);
             break;
    }

    return off;
}

unsigned long usGetMemberAddr(unsigned long ulModule, unsigned long ulMember)
{   
    unsigned long Address;   

    Address = (unsigned long)&taModulesArray[ulModule] + find_offset(ulMember);

    return Address; 
} 


回答2:

You could do it by using a helper array, using offsetof:

typedef struct{               
  unsigned char MrChar;
  unsigned short MrShort;
  unsigned long MrLong;
  unsigned char MrArray[5];
}tModule;

size_t offsets[] = {
  offsetof(tModule, MrChar),
  offsetof(tModule, MrShort),
  offsetof(tModule, MrLong),
  offsetof(tModule, MrArray)
};

unsigned long usGetMemberAddr(unsigned long ulModule, unsigned long ulMember){
  unsigned long Address;
  Address = abs((char *)&taModulesArray            // base of taModulesArray
             - ((char *)&taModulesArray[ulModule]  // start of this module
                + offsets[ulMember]));             // + offset of member
  return Address;
}

Note that your formula could be simplified as:

  Address = (char *)&taModulesArray[ulModule]
           - (char *)&taModulesArray
           + offsets[ulMember];

Or even further:

  Address = ulModule * sizeof(tModule) + offsets[ulMember];

Note: offsetof is defined in stddef.h. See this Wikipedia article for more.

If your compiler doesn't have this, one implementation of offsetof could be:

#define offsetof(st, m) \
     ((size_t) ( (char *)&((st *)0)->m - (char *)0 ))