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

前端 未结 5 1061
生来不讨喜
生来不讨喜 2020-12-18 07:31

The C faqs explain it in a way, here is the link.

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

Thanks so much!

相关标签:
5条回答
  • 2020-12-18 07:44

    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.

    0 讨论(0)
  • 2020-12-18 07:46

    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 讨论(0)
  • 2020-12-18 07:49

    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;
    
    }
    
    0 讨论(0)
  • 2020-12-18 07:58

    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].

    0 讨论(0)
  • 2020-12-18 07:59

    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.

    0 讨论(0)
提交回复
热议问题