如何获取结构数组中某些struct成员的地址

时间:2012-08-06 09:51:28

标签: c struct member memory-address

我尝试在结构数组中获取某个struct成员的地址,但我不想使用该成员的名称。

它应该是这样的:

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;
}

我需要快速修改不同结构的配置(在EEPROM中)。所以我尝试做一个模块成员之一的模块和索引的函数并返回适当成员的偏移量。

如果在返回之前有任何类似该行的可能性?

2 个答案:

答案 0 :(得分:3)

您可以使用帮助器数组,使用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;
}

请注意,您的公式可以简化为:

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

甚至更进一步:

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

注意:offsetofstddef.h中定义。有关详情,请参阅此Wikipedia article

如果您的编译器没有这个,offsetof的一个实现可能是:

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

答案 1 :(得分:0)

我们也可以使用下面的逻辑来查找结构中每个成员的偏移量,然后我们可以直接将它添加到结构变量的特定实例的基本地址中。

#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; 
}