开发者

How can I access structure fields by name at run time?

开发者 https://www.devze.com 2022-12-24 07:18 出处:网络
The C faqs explain it in a way, here is开发者_JS百科 the link. But I can\'t understand it, Somebody can explain it for me? Or give me another way?

The C faqs explain it in a way, here is开发者_JS百科 the link.

But I can't understand it, Somebody can explain it for me? Or give me another way?

Thanks so much!


I think this example makes the answer clear:

struct test
{
    int b;
    int a;
};

int main() 
{
    test t;
    test* structp = &t;

    //Find the byte offset of 'a' within the structure
    int offsetf = offsetof(test, a);

    //Set the value of 'a' using pointer arithmetic
    *(int *)((char *)structp + offsetf) = 5;

    return 0;

}


You can't, not without implementing some kind of name lookup yourself.

C doesn't have any time of name information left when the program is running.

Supporting this generally for different struct field types is complicated.


If you have your binary compiled with debug information, you can use it to lookup names at runtime. For example gcc (typically) produces debug info in DWARF format, and you can use libdwarf to process it.

In case of DWARF you can find your field in DW_TAG_member node, DW_AT_data_member_location attribute will give you the field's offset, same as you get from offsetof() at compile time.


If a structure is defined using a struct {...} definition, it is unlikely that there will be any information in the executable code related to member names. Some platforms build "debug" information into generated executable files, and there may be some means by which a running program could retrieve that information, but there's no common way to do such things.

What one may be able to do, however, is use macros to define a structure. For example, one could define:

#define MAKE_ACME_STRUCT \
  FIELD(id,int,23) \
  X FIELD(name,char30,"Untitled") \
  X FIELD(info,int,19) \
  // LEAVE THIS COMMENT HERE

and then invoke the MAKE_ACME_STRUCT macro various times, with the FIELD and X macros defined different ways, so that it would expand either to a struct statement, or an initialization expression for a "default" instance of that struct, or as an initialization expression for an array of items describing the struct fields [e.g. something like

STRUCT_INFO acme_struct_info[] = {
  {"id", STRUCT_INFO_TYPE_int, sizeof(ACME_STRUCT.id), offsetof(ACME_STRUCT.id)}
  ,{"name", STRUCT_INFO_TYPE_char30, sizeof(ACME_STRUCT.name), offsetof(ACME_STRUCT.name)}
  ,{"info", STRUCT_INFO_TYPE_int, sizeof(ACME_STRUCT.info), offsetof(ACME_STRUCT.info)}
  ,{0}};

It would be necessary that all types used within the struct have single-token names, and that for each such name, an identifier STRUCT_INFO_TYPE_nameGoesHere be defined which identifies the type to a run-time library in some form that it understands.

Such macros are hardly beautiful, but they have the advantage of ensuring that all the things they're used to define remain in sync [e.g. ensuring that adding or removing an element of acme_struct will cause it to be added or removed from the list of struct members stored in acme_struct_info].


Keep track of the field offsets as computed using the offsetof() macro. If structp is a pointer to an instance of the structure, and field f is an int having offset offsetf, f's value can be set indirectly with

*(int *)((char *)structp + offsetf) = value;
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号