Home > Net >  Read from structures with same members at different offsets in C
Read from structures with same members at different offsets in C

Time:11-10

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:

https://godbolt.org/z/a73YsorMe

  • Related