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

C faqs以某种方式解释它, 这里是链接。

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

非常感谢!

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

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; } 

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

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

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

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

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

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

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

如果使用struct {...}定义定义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_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 ,以便以它理解的某种forms标识运行时库的类型。

这样的宏几乎不漂亮,但它们的优点是可以确保它们用于定义的所有内容保持同步[例如,确保添加或删除acme_struct的元素将导致它从struct列表中添加或删除成员存储在acme_struct_info ]中。