我可以动态地使用名称列表来访问变量吗?

时间:2018-04-16 13:02:22

标签: c

我有一个变量列表char [][20] ls = {"var_1", "var_2", ... , ""}

是结构struct {char var1[10], ...} my_struct;

的字段名称

结构中的变量都是char[],长度不断变化。 列表本身是const,不应在运行中期间更改。

我想以一种通用的方式在循环中访问这些变量。我宁愿拥有:

,而不是打电话给myfunc(my_struct.var1); myfunc(my_struct.var2);等等
for (char * p = ls[0]; *p; p += sizeof(ls[0]))
{
  myfunc(my_struct.{some magic that would put var_1 / var_2 here});
}

但我想这是不可能的,因为循环是在运行时执行的,变量名需要在编译时可用。

我是否正确或有什么可以在这里完成的吗? (不一定要这样,只想知道我是否可以把这个例程打包成一个很好的循环)

2 个答案:

答案 0 :(得分:5)

由于所有成员都是相同类型的数组,因此您可以为每个成员创建一个地址数组并循环遍历:

char *my_struct_addrs[] = { my_struct.var1, my_struct.var2, ... };
int i;
for (i=0; i < sizeof(my_struct_addrs) / sizeof(my_struct_addrs[0]); i++) {
    myfunc(my_struct_addrs[i]);
}

由于每个数组的大小不同,因此您需要注意不要传递每个数组的范围。你可以通过跟踪每个字段的大小并将其传递给函数来解决这个问题:

struct addr_list {
    char *addr;
    int len;
};

struct addr_list my_struct_addrs[] = { 
    { my_struct.var1, sizeof(my_struct.var1) },
    { my_struct.var2, sizeof(my_struct.var2) },
    ...
};

int i;
for (i=0; i < sizeof(my_struct_addrs) / sizeof(my_struct_addrs[0]); i++) {
    myfunc(my_struct_addrs[i].addr, my_struct_addrs[i].len);
}

答案 1 :(得分:1)

假设您有类似

的内容
B

这个列表没有与struct数据紧密耦合(如果是这样你可以使用dbush的答案),但无论出于何种原因它都是一个单独的项目。

然后,稍微苛刻但定义明确的版本将使用查找表。创建两个查找表,一个包含字符串,另一个包含偏移量:

const char* ls[] = {"var_1", "var_2", ""};

然后执行#include <stddef.h> typedef struct { int var_1; int var_2; } my_struct_t; static const char* VAR_STRINGS[] = { "var_1", "var_2", "" }; static const size_t VAR_OFFSET[] = { offsetof(my_struct_t, var_1), offsetof(my_struct_t, var_2), }; 之类的操作来获取索引。 (遍历所有项目,或使用二进制搜索等)。以下代码实际上是合法且明确定义的:

index = search_in_VAR_STRINGS_for(ls[i]);

这需要考虑填充,并且C11 6.3.2.3/7保证指针算术正常:

  

当指向对象的指针转换为指向字符类型的指针时,   结果指向对象的最低寻址字节。连续增量   结果,直到对象的大小,产生指向对象剩余字节的指针。

由于真正存储在该地址(有效类型)的确是unsigned char* ptr = (unsigned char*)&my_struct; ptr += VAR_OFFSET[index]; int var_1 = *(int*)ptr; ,因此C11 6.5 / 7(“严格别名”)保证变量访问正常。 :

  

对象的存储值只能由具有其中一个的左值表达式访问   以下类型:
   - 与对象的有效类型兼容的类型,

但显然需要进行各种错误处理,以检查某些事情是否超出范围。