如果你没有被传递的结构的类型(就像你的 void* 建议的那样),基本上你注定要失败。它们只是一堆有起始地址的内存。
你可以做的是有几个函数,比如你建议的 update_fields,并根据结构的类型以某种方式调用正确的函数(那个很简单,也可以相当隐藏在宏中以避免语法噪音)。
这样做你会得到如下代码:
#include <stdio.h>
#include <string.h>
typedef struct {
char street[10];
char city[10];
char lat[10];
char lon[10];
} ADDR_A;
typedef struct {
char street[10];
char city[10];
char zip[10];
char country[10];
} ADDR_B;
#define UPDATEFIELDS(type, value) updateFields_##type(value)
static void updateFields_ADDR_A(ADDR_A *myStruct ) {
strcpy(myStruct->street, "abc" );
strcpy(myStruct->city, "def" );
}
static void updateFields_ADDR_B(ADDR_B *myStruct ) {
strcpy(myStruct->street, "abc" );
strcpy(myStruct->city, "def" );
}
int main(){
ADDR_A a;
ADDR_B b;
updateFields_ADDR_A(&a);
updateFields_ADDR_B(&b);
UPDATEFIELDS(ADDR_A, &a);
printf("%s\n", a.city);
printf("%s\n", b.city);
}
请注意,您显然不应该在 updateFields_XXX 函数中编写实际的字段更改代码,而只需使用该代码作为包装器来获取内部字段的正确偏移量。
我你也想有代码局部性,你可以再次使用宏,
#define COMMONBODY strcpy(myStruct->street, "abc" );\
strcpy(myStruct->city, "def" );
static void updateFields_ADDR_A(ADDR_A *myStruct ) {
COMMON_BODY
}
static void updateFields_ADDR_B(ADDR_B *myStruct ) {
COMMON_BODY
}
甚至将通用代码放在一个单独的文件中并包含两次(非常不寻常,但可以工作的文件)
static void updateFields_ADDR_A(ADDR_A *myStruct ) {
#include "commonbody.c"
}
static void updateFields_ADDR_B(ADDR_B *myStruct ) {
#include "commonbody.c"
}
除了名称修饰部分之外,使用 typeof 运算符也几乎有可能(但据我所知并不完全)。
如果您的结构大小不同,我们甚至可以只使用一个 updateFields 函数(带有 void*),它将结构的大小作为第二个参数,并使用它自动转换为正确的类型。这很脏但可能[如果有人想看到开发该解决方案,请发表评论]。
您也可以使用联合。如果有一个公共前缀,则可以使用任何联合成员访问公共字段(但我知道不是这样)。您必须了解,定义这样的联合不会改变现有数据结构的任何内容。这基本上定义了一个 ADDR_A 或 ADDR_B 类型,而不是可以使用指针引用。
typedef union {
ADDR_A a;
ADDR_B b;
} ADDR_A_or_B;
如果有公共前缀,您可以使用任何访问器字段设置这些变量:
static void updateFields(ADDR_A_or_B *myStruct ) {
strcpy( myStruct->a.street, someStreeValueFromSomewhereElse);
strcpy( myStruct->a.city, someCityValueFromSomewhereElse);
}
你只需要在调用时进行投射:
ADDR_A a;
updateFields((ADDR_A_or_B *)&a);
ADDR_B b;
updateFields((ADDR_A_or_B *)&b);