2008-09-15 38 views
3

我有一些代码具有多种功能非常相似,相互查找一个项目中基于一个字段的结构的内容列表。函数之间的唯一区别是查找出现的结构类型。如果我可以传入该类型,则可以删除所有代码重复。有没有什么办法的结构类型传递给C函数

我也注意到有一些互斥锁定在这些功能发生一样,所以我想我可能会离开他们独自...

回答

0

一种方式做到这一点是有一个类型字段作为第一个字节的结构。您的接收函数将查看此字节,然后根据它发现的内容将指针转换为正确的类型。另一种方法是将类型信息作为单独的参数传递给每个需要它的函数。

3

由于结构只不过是预定义的内存块,所以可以这样做。你可以传递一个void *给结构体,以及一个整数或者某个东西来定义类型。

从那里开始,要做的事情是在访问数据之前将void *重新转换为适当类型的指针。

你需要非常非常小心,因为你失去的类型安全,当你投以一个void *,做这样的事情时,你可以有可能与一个难以调试运行时错误而告终。

-1

我第C有点生疏,但尝试使用一个void *指针作为函数参数的变量类型。然后将该结构的地址传递给该函数,然后按照你想要的方式使用它。

void foo(void* obj); 

void main() 
{ 
    struct bla obj; 
    ... 
    foo(&obj); 
    ... 
} 

void foo(void* obj) 
{ 
    printf(obj -> x, "%s") 
} 
+0

这是不可能编译的。你不能像这样取消引用无效的指针。 – 2008-09-15 23:12:03

+0

好吧,公平地说,我确实说过我在C生锈了;) – 2008-09-16 20:47:46

6

如果您确保该字段放置在每个此类结构中的相同位置,则可以简单地投射一个指针以获取该字段。该技术用于许多低级系统库,例如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; 
} 

这样做会使您丧失安全性,但这是一项有价值的技术。

[我现在已经实际测试上面的代码和固定各种小错误。当你有一个编译器时,它会容易得多。 ]

0

您可以用参数化宏但大部分编码策略做将皱眉说。


#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)); 
} 
0

简答:没有。但是,您可以创建自己的方法,即提供有关如何创建此类结构的规范。但是,这通常是不必要的,不值得付出努力;只是通过参考传递。 (callFuncWithInputThenOutput(input, &struct.output);

1

我想你应该看看C标准函数的qsort()和bsearch()的灵感。这些是用于对数组进行排序并在预先排序的数组中搜索数据的通用代码。他们可以处理任何类型的数据结构 - 但是你可以向它们传递一个指向帮助函数的指针来进行比较。帮助函数知道结构的细节,因此正确地进行比较。实际上,既然你想做搜索,可能你所需要的只是bsearch(),但是如果你正在建立数据结构,你可能会决定你需要一个不同的结构而不是一个排序名单。 (你可以使用排序列表 - 与堆比较,它往往会减慢速度。然而,你需要一个通用的heap_search()函数和一个heap_insert()函数来正确地完成这项工作,而这些函数在C中没有标准化。搜索web显示这样的函数存在 - 而不是这个名称;只是不要试图“C堆搜索”,因为它假定你的意思是“廉价的搜索”,你会得到吨垃圾!)

1

如果ID字段,你的测试是由所有的共享领域的公共初始序列的一部分结构,然后采用联合担保的访问将工作:

#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; 
} 

如果你运气不好,和外地出现在各种结构不同的偏移量,你可以偏移参数添加到您的功能。然后,offsetof和一个封装宏模拟OP所要求的 - 在调用位置传递struct的类型:

#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; 
} 
相关问题