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数组,使用
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]; |
注:
如果编译器没有此功能,那么
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; } |