### 如何根据C中的变量整数访问`struct'的成员？

``````struct Element {
unsigned int a1 : 1;
unsigned int a2 : 1;
...
unsigned int an : 1;
};
``````

``````int getval(struct Element *ep, int n)
{
int val;
switch(n) {
case 1: val = ep->a1; break;
case 2: val = ep->a2; break;
...
case n: val = ep->an; break;
}
return val;
}
``````

`````` #define getval(s,n)   s.a##n
``````

#### 12 个答案:

• 不同规模的会员
• 包装问题
• 对齐问题
• 像位域这样的技巧会有问题

``````int getval(struct Element *ep, int n)
{
return *(((int*)ep) + n);
}
``````

``````int offsets[3];
void initOffsets()
{
struct Element e;
offsets[0] = (int)&e.x - (int)&e;
offsets[1] = (int)&e.y - (int)&e;
offsets[2] = (int)&e.z - (int)&e;
}

int getval(struct Element *ep, int n)
{
return *((int*)((int)ep+offsets[n]));
}
``````

``````double getDoubleVal(struct Element *ep, int n)
{
return *((double*)((int)ep+offsets[n]));
}
``````

``````template<typename T>
T getval(struct Element *ep, int n)
{
return *((T*)((int)ep+offsets[n]));
}
``````

``````struct Element {
unsigned int a1 : 1;
unsigned int a2 : 1;
...
unsigned int an : 1;
};

typedef unsigned int (*get_fn)(const struct Element*);

#define DEFINE_GETTER(ARG) \
unsigned int getter_##ARG (const struct Element *ep) { \
return ep-> a##ARG ; \
}

DEFINE_GETTER(1);
DEFINE_GETTER(2);
...
DEFINE_GETTER(N);

get_fn jump_table[n] = { getter_1, getter_2, ... getter_n};

int getval(struct Element *ep, int n) {
return jump_table[n-1](ep);
}
``````

``````int getval(const struct Element *ep, int n)
{
switch(n)
{
case 1: return ep->a1;
case 2: return ep->a2;
/* And so on ... */
}
return -1; /* Indicates illegal field index. */
}
``````

``````val = getfield_aN( myobject, n );
``````

``````val = getfield_foo( myobject );
``````

``````struct  int_pointers
{
int  *ptr1;
int  *ptr2;
long *ptr3;
double *ptr4;
std::string * strDescrPtr;

};
``````

``````struct int_pointers  ptrs;
int  i1 = 154;
int i2 = -97;
long i3 = 100000;
double i4  = (double)i1/i2;
std::string strDescr = "sample-string";
ptrs.ptr1 =  &i1;
ptrs.ptr2 =  &i2;
ptrs.ptr3 = &i3;
ptrs.ptr4 = &i4;
ptrs.strDescrPtr = &strDescr;
``````

``````int GetIntVal (struct int_pointers *ep, int intByteOffset)
{
int * intValuePtr =  (int *)(*(int*)((int)ep + intByteOffset));
return *intValuePtr;
}
``````

``````int intResult = GetIntVal(&ptrs,0) //to retrieve the first int value in ptrs structure variable

int intResult = GetIntVal(&ptrs,4) //to retrieve the second int value in ptrs structure variable
``````

``````struct Whang {
int a1;
int a2;
int getIth(int i) {
int rval;
switch (i) {
case 1: rval = a1; break;
case 2: rval = a2; break;
default : rval = -1; break;
}
return rval;
}
};

int _tmain(int argc, _TCHAR* argv[])
{
Whang w;
w.a1 = 1;
w.a2 = 200;

int r = w.getIth(1);

r = w.getIth(2);

return 0;
}
``````

`getIth()`会了解`Whang`的内部结构，并且可以处理它所包含的内容。

``````void writebit(char *array, int n)
{
char mask = (1 << n);
*array = *array & mask;
}
``````

``````int getval(struct Element *ep, int n)
``````

``````ep->a1
``````

``````typedef struct _FieldType
{
int size_in_bits;
} FieldType;
``````

``````FieldType structure_def [] = { {1}, {1}, {1}, {4}, {1}, {0} };
``````

``````typedef struct _Element
{
FieldType *fields;
} Element;
``````

``````Element *CreateElement (FieldType *field_defs)
{
/* calculate number of bits defined by field_defs */
int size = ?;
/* allocate memory */
Element *element = malloc (sizeof (Element) + (size + 7) / 8); /* replace 7 and 8 with bits per char */
element->fields = field_defs;
return element;
}
``````

``````int GetValue (Element *element, int field)
{
/* get number of bits in fields 0..(field - 1) */
int bit_offset = ?;
/* get char offset */
int byte_offset = sizeof (Element) + bit_offset / 8;
/* get pointer to byte containing start of data */
char *ptr = ((char *) element) + byte_offset;
/* extract bits of interest */
int value = ?;
return value;
}
``````

1. 只有位字段或结构中的所有位域
2. 小于32（或64）个位域
3. 然后这个解决方案适合你。

``````#include <stdio.h>
#include <stdint.h>

struct Element {
unsigned int a1 : 1;
unsigned int a2 : 1;
unsigned int a3 : 1;
unsigned int a4 : 1;
};

#define ELEMENT_COUNT 4 /* the number of bit fields in the struct */

/* returns the bit at position N, or -1 on error (n out of bounds) */
int getval(struct Element* ep, int n)
{
if(n > ELEMENT_COUNT || n < 1)
return -1;

/* this union makes it possible to access bit fields at the beginning of
the struct Element as if they were a number.
*/
union {
struct Element el;
uint32_t bits;
} comb;

comb.el = *ep;
/* check if nth bit is set */
if(comb.bits & (1<<(n-1))) {
return 1;
} else {
return 0;
}
}

int main(int argc, char** argv)
{
int i;
struct Element el;

el.a1 = 0;
el.a2 = 1;
el.a3 = 1;
el.a4 = 0;

for(i = 1; i <= ELEMENT_COUNT; ++i) {
printf("el.a%d = %d\n", i, getval(&el, i));
}

printf("el.a%d = %d\n", 8, getval(&el, 8));

return 0;
}
``````