For the problem, consider below two structures.
struct type1_A
{
int a;
char b;
char rsvd[10];
char c;
int d;
}
struct type1_B
{
int d;
char rsvd[12];
char c;
char b;
int a;
}
I need to read fields a, b, c & d from the structs. I will have a buffer address and that buffer will have one of the struct. A flag can tell what kind of struct it is.
if (flag == TYPE1_A) {
a = ((struct type1_A*) (buffer))->a;
}
else if (flag == TYPE1_B) {
a = ((struct type1_B*) (buffer))->a;
}
But when there are many such reads, I dont want to keep on having if-else like above. Is there some way (hack) that this can be done without if-else. The field names will be same but at a different offset.
CodePudding user response:
You can do the pointer arithmetic manually and store the offsets in a table indexed by type. That'd replace the if-else ladder with a table lookup:
if(flag_is_within_type_range(flag))
a=*(int*) ((char*)buffer offset_table_indexed_by_type[flag]);
Essentially the resulting assembly needs to do a dynamic_type_number-to-an_offset lookup and you having the same overloaded name (i.e., the a
member) for those different offsets doesn't help anything. There's hardly any good way to exploit it.
CodePudding user response:
I would use macro like this:
#define TYPE_1 1
#define GETMEMBER(type, buff, field) ((type) == TYPE_1 ? ((struct type1_A *)(buff)) -> field : ((struct type1_B *)(buff)) -> field)
void foo(void *buff)
{
int type1a = GETMEMBER(TYPE_1, buff, a);
int type2a = GETMEMBER(0, buff, a);
printf("Type1: %d, type2:%d\n", type1a, type2a);
}
If you use a constant expression as type
the compiler will optimize out the comparison leaving only the assignment: