我有一些代码,其中多个函数非常相似,根据结构中一个字段的内容查找列表中的项目。这些函数之间唯一的区别是发生查找的结构类型。如果我可以传入类型,就可以消除所有代码重复。
我还注意到这些函数中也发生了一些互斥锁定,因此我认为最好不要动它们...
我有一些代码,其中多个函数非常相似,根据结构中一个字段的内容查找列表中的项目。这些函数之间唯一的区别是发生查找的结构类型。如果我可以传入类型,就可以消除所有代码重复。
我还注意到这些函数中也发生了一些互斥锁定,因此我认为最好不要动它们...
如果您确保该字段在每个这样的结构中都放置在相同的位置,那么您可以简单地进行指针转换以访问该字段。这种技术在许多低级系统库(例如BSD套接字)中使用。
struct person {
int index;
};
struct clown {
int index;
char *hat;
};
/* we're not going to define a firetruck here */
struct firetruck;
struct fireman {
int index;
struct firetruck *truck;
};
int getindexof(struct person *who)
{
return who->index;
}
int main(int argc, char *argv[])
{
struct fireman sam;
/* somehow sam gets initialised */
sam.index = 5;
int index = getindexof((struct person *) &sam);
printf("Sam's index is %d\n", index);
return 0;
}
虽然这样做会失去类型安全,但这是一种有价值的技术。
[ 我现在已经测试了上面的代码并修复了各种小错误。当你有编译器时,这会更容易。 ]
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int id;
long junk2;
} Bar;
typedef union
{
struct
{
int id;
} common;
Foo foo;
Bar bar;
} U;
int matches(const U *candidate, int wanted)
{
return candidate->common.id == wanted;
}
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 42, 0 };
U fu;
U bu;
fu.foo = f;
bu.bar = b;
puts(matches(&fu, 23) ? "true" : "false");
puts(matches(&bu, 42) ? "true" : "false");
return 0;
}
#include <stddef.h>
#include <stdio.h>
typedef struct
{
int id;
int junk1;
} Foo;
typedef struct
{
int junk2;
int id;
} Bar;
int matches(const void* candidate, size_t idOffset, int wanted)
{
return *(int*)((const unsigned char*)candidate + idOffset) == wanted;
}
#define MATCHES(type, candidate, wanted) matches(candidate, offsetof(type, id), wanted)
int main(void)
{
Foo f = { 23, 0 };
Bar b = { 0, 42 };
puts(MATCHES(Foo, &f, 23) ? "true" : "false");
puts(MATCHES(Bar, &b, 42) ? "true" : "false");
return 0;
}
我认为你应该看一下C标准函数qsort()和bsearch(),以获取灵感。这些是通用代码,用于对数组进行排序并在预排序的数组中搜索数据。它们适用于任何类型的数据结构 - 但是您需要向它们传递一个指向执行比较的帮助函数的指针。帮助函数知道结构的细节,因此可以正确地进行比较。
实际上,由于您想要进行搜索,可能只需要bsearch(),但如果您正在动态构建数据结构,则可能决定需要与排序列表不同的结构。(您可以使用排序列表 - 它只会使事情变慢,与堆相比,例如。但是,您需要一个通用的heap_search()函数和一个heap_insert()函数才能正确完成工作,而这些函数在C中没有标准化。通过搜索网络,可以发现这样的函数存在 - 不是以那个名称命名的;只是不要尝试“c heap search”,因为假定您的意思是“cheap search”,您会得到大量垃圾!)
你可以用参数化宏来实现这个,但是大多数编程规范都会不赞同这种做法。
#include
#define getfield(s, name) ((s).name)
typedef struct{
int x;
}Bob;
typedef struct{
int y;
}Fred;
int main(int argc, char**argv){
Bob b;
b.x=6;
Fred f;
f.y=7;
printf("%d, %d\n", getfield(b, x), getfield(f, y));
}
简短回答:不行。但是,你可以自己创建一种方法来实现这样的结构体,即提供一个创建此类结构体的规范。然而,这通常是不必要的,也不值得花费精力;只需通过引用传递即可。(callFuncWithInputThenOutput(input, &struct.output);
)
我对 C 有点生疏,但可以尝试在函数参数中使用 void* 指针作为变量类型。然后将结构体的地址传递给函数,并像平常一样使用它。
void foo(void* obj);
void main()
{
struct bla obj;
...
foo(&obj);
...
}
void foo(void* obj)
{
printf(obj -> x, "%s")
}
char
类型的项放置在偏移量0以外的风险。如果该字段出现在其他位置,则可能会出现问题。 - Jonathan Leffler