C:是否可以将指针关联到结构成员?

C: is it possible to associate a pointer to a structure member?

我想创建类似映射数组的东西,以便将来开发某些模块。这个想法是让一个字符串由外部函数执行,该函数总是 returns 一个字符串,结果需要解析为正确的格式,然后将其存储在 structure() 的特定成员中。使用特定功能很容易做到这一点,但我想使用更通用的方法和功能,如 atoi(或它的重新创建版本),如果将来可能实现可移植性和快速实现的话。 我创建了以下结构来保存这样的映射数据:

typedef struct sMapping
{
    const char *string;
    int (* function)();
    void *storage;
} tMapping;

然后创建了这样一个数组,将某些内容映射到前 2 个值:

tMapping mapTest[]={
    { .string = "name", .function = te_strcpy},
    { .string = "age", .function = te_atoi},
    { .string = "location", .function = te_parse},
    { .string = "height", .function = te_atoi}
};

我想在代码中主要是这样的:

char *outputstr = NULL;
for(i = 0; i<MAX_LEAFS; i++)
{
    if(mapTest[i].string == NULL)
        break;

    outputstr = fct_lookup_option_string(mapTest[i].string);
    mapTest[i].function(outputstr);
}

到目前为止,一切正常,一切都得到了很好的解析。请注意,te_atoi 函数提取了 2 个变量。

现在如果我有另一个像

这样的结构
typedef struct sSave
{
    char* name;
    int age;
    struct geo *location;
    int height;
} tSave;

tSave person;

并想将某些东西映射到它

(CODE BELOW IS NOT CORRECT, I KNOW, JUST WANT TO PRESENT MY IDEA BETTER)
tMapping mapTest[]={
    { .string = "name", .function = te_strcpy, .storage= &(person.name)}, 
    { .string = "age", .function = te_atoi, .storage= &(person.age)},
    { .string = "location", .function = te_parse, .storage= &(person.location)},
    { .string = "heigth", .function = te_atoi, .storage= &(person.height)},
};

使用类似

的东西
(CODE BELOW IS NOT CORRECT, I KNOW, JUST WANT TO PRESENT MY IDEA BETTER)
mapTest[i].storage = mapTest[i].function(outputstr);

这可能吗?有任何想法吗?双指针? C++?魔法?黑魔法?

谢谢。

请记住,我想将其用作多个模块(甚至可能是一些自动化)的通用模板,因此特定功能会对此有所限制。

非常有趣的项目。它一定是有动力去做的。

您的想法似乎不错,不需要 C++,但黑魔法可能会有所帮助:-)。

说真的:是的,可以将指针关联到结构成员。对于char,short,int和long,我认为你这样做是可以的。

对于字符串和结构,解析器必须分配内存。对于字符串,将 te_strcpy 替换为 te_strdup 应该可以。

对于结构来说有点复杂:你必须告诉解析器内存分配结构的大小并描述结构的内容才能正确填充它。 为此,一种解决方案可能是在 tMapping 结构中添加这些信息:

typedef struct sMapping
{
    const char *string;
    int (*function)(char*, void*);
    void *functionParam; // for a te_parse function this param could be a struct containing a tMapping array and a target struct to fill
    void *storage;
} tMapping;

mapTest 数组变为:

tMapping mapTest[]={
    { .string = "name", .function = te_strdup, .storage= &(person.name)}, 
    { .string = "age", .function = te_atoi, .storage= &(person.age)},
    { .string = "location", .function = te_parse, .functionParam=sMapGeo, .storage= &(person.location)},
    { .string = "height", .function = te_atoi, .storage= &(person.height)},
};

要具有通用 te_parse 函数,sMapGeo 结构可以是:

(THIS CODE WON'T WORK AS IS, BUT IT EXPLAINS THE IDEA)
 struct {
    void *structToFill = &saveGeo;
    int structSize = sizeof(saveGeo);
    tMapping mapStruct[] = 
    { .string="city", .function=te_strdup, .storage=&(saveGeo.city)}
    etc.
 } sMapGeo;

那么 te_parse 函数应该如下所示:

void *te_parse(char *input, tParseMap *sMap)
{
    applyMapping(sMap->mapStruct); //apply the mapping like the main mapping
    char *mem = malloc(sMap->structSize);
    memcpy(mem, sMap->structToFill, sMap->structSize));
    return mem;
}

最后一件小事。由于存储是一个指针,所以不要忘记 * 为指向的内容赋值:

*mapTest[i].storage = mapTest[i].function(outputstr, mapTest[i].functionParam);

毕竟,处理浮点数、双精度数、数组甚至使代码与 32 位和 64 位体系结构兼容都是另一回事!