关于C#:如何获取结构数组中某个struct成员的地址

How to get address of some struct member in array of structures

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

应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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中)不同结构的配置。所以我尝试做一个函数,它获取模块的个数和一个模块成员的索引,并返回适当成员的偏移量。

在返回之前,是否有可能出现类似的情况?


您可以使用一个helper数组,使用offsetof来完成此操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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;
}

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

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

或者更进一步:

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

注:offsetofstddef.h中定义。更多信息请参见维基百科的这篇文章。

如果编译器没有此功能,那么offsetof的一个实现可以是:

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


我们还可以使用下面的逻辑来查找结构的每个memeber的偏移量,然后直接将其添加到结构变量的特定实例的基addres中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#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;
}