如何在运行时按名称访问结构字段?

时间:2010-03-25 13:08:24

标签: c struct

C faqs以某种方式解释它,here is the link.

但我无法理解,有人能为我解释一下吗?或者给我另一种方式?

非常感谢!

5 个答案:

答案 0 :(得分:6)

我认为这个例子清楚地说明了答案:

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;

}

答案 1 :(得分:1)

你不能,不能没有自己实现某种名称查找。

当程序运行时,C没有任何时间留下名称信息。

通常对不同的结构字段类型支持这一点很复杂。

答案 2 :(得分:1)

如果您使用调试信息编译了二进制文件,则可以使用它在运行时查找名称。例如gcc(通常)以DWARF格式生成调试信息,您可以使用libdwarf来处理它。

如果是DWARF,您可以在DW_TAG_member节点中找到您的字段,DW_AT_data_member_location属性将为您提供字段的偏移量,与您在编译时从offsetof()获得的相同。

答案 3 :(得分:0)

跟踪使用offsetof()宏计算的字段偏移量。如果structp是指向结构实例的指针,并且字段f是具有偏移offsetf的int,则可以使用

间接设置f的值
*(int *)((char *)structp + offsetf) = value;

答案 4 :(得分:0)

如果使用struct {...}定义定义结构,则可执行代码中不可能存在与成员名称相关的任何信息。一些平台将“调试”信息构建到生成的可执行文件中,并且可能有一些方法可以使正在运行的程序检索该信息,但是没有通用的方法来执行此类操作。

但是,可以使用宏来定义结构。例如,可以定义:

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

然后多次调用MAKE_ACME_STRUCT宏,并且FIELD和X宏定义了不同的方式,以便它可以扩展为struct语句,或者扩展为该结构的“默认”实例的初始化表达式,或者作为描述struct字段的项数组的初始化表达式[例如

之类的东西
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}};

结构中使用的所有类型都必须具有单令牌名称,并且对于每个这样的名称,必须定义标识符STRUCT_INFO_TYPE_nameGoesHere,以某种形式标识运行时库的类型它理解。

这些宏并不漂亮,但它们的优势在于确保它们用于定义的所有内容保持同步[例如确保添加或删除acme_struct元素会导致在acme_struct_info]中存储的struct成员列表中添加或删除它。