我有一个变量列表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});
}
但我想这是不可能的,因为循环是在运行时执行的,变量名需要在编译时可用。
我是否正确或有什么可以在这里完成的吗? (不一定要这样,只想知道我是否可以把这个例程打包成一个很好的循环)
答案 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(“严格别名”)保证变量访问正常。 :
对象的存储值只能由具有其中一个的左值表达式访问 以下类型:
- 与对象的有效类型兼容的类型,
但显然需要进行各种错误处理,以检查某些事情是否超出范围。