我在C(嵌入式编程)中有grep函数,它将void指针作为参数。该函数需要能够处理不同类型的变量,如字符整数和长整数。我如何编写函数代码,以便它可以自己弄清楚我传递的是什么类型的变量?我不知道这是否可行。感谢
即。
void grep( void *t )
{
if( t == char )
{
do this
}
if( t == int )
{
do that
}
...
}
答案 0 :(得分:14)
任何准确性都无法做到。例如,4字节整数可以很容易地解释为字符串。例如,空终止字符串“ABC”将与整数值1094861568相同(取决于字节顺序)。
答案 1 :(得分:6)
Void指针只包含存储数据的内存位置。您无法从中推断出任何类型信息。但你可以做的是,将两个参数传递给你的函数,一个用于类型,另一个传递给指针。
如果您可以使用C ++,您可以创建一组重载的辅助函数来提供类型信息。
答案 2 :(得分:5)
这在C中是不可能的。您必须明确指出参数的预期类型。您将必须传递第二个参数或传递具有类型信息作为参数的联合或结构。
答案 3 :(得分:3)
你基本上是在C中询问如何做introspection。不幸的是,这不是受支持的功能。
相反,你可以像@ anand.arumug指出的那样使用像grep_char这样的函数。或者(如果可能的话)您可以转移到C ++并使用其功能重载功能。
答案 4 :(得分:3)
直接回答:这是不可能的。此外,您应该避免编写这样的超级函数,这些函数可以在多种类型上运行2,而您无法真正概括代码并应用多态。在C中,这通常涉及函数指针。否则,编写每个单独类型的多个函数都没有错。事实上,这应该优于超级功能。
这是一个基本的例子(不是很有用,但很简单):
#include <stdio.h>
typedef int less_function(void*, void*);
struct foo
{
int data;
};
int foo_less(void* a, void* b)
{
struct foo* f1 = a;
struct foo* f2 = b;
return f1->data < f2->data;
}
int find(void* search_array, void* element, int num, int element_size, less_function* less)
{
int j = 0;
char* search_pos = search_array;
for (j=0; j < num; ++j, search_pos += element_size)
{
// if current element == element to find
if (!less(search_pos, element) && !less(element, search_pos) )
return j;
}
return -1;
}
int main()
{
struct foo my_array[10] = { {0}, {1}, {2}, {3}, {4}, {5}, {6}, {123}, {7}, {8} };
struct foo search_element = {123};
// outputs 7
printf("%d\n", find(my_array, &search_element, 10, sizeof(struct foo), foo_less) );
}
在上面的代码中,你可以看到我没有像这样的代码:如果这个类型是一个整数,那么,如果它是一个浮点数,那么这样做,如果它是一个struct foo对象,那么这样做等等。相反,我们依赖函数指针来提供自定义行为,以便比较传入的对象类型。
qsort 也是这样做的,这是一个很好的例子。它与上面的find函数非常相似,除了它的比较器不会根据第一个对象是否小于另一个而返回true / false:它就像strcmp并返回0,-1或+1。
答案 5 :(得分:2)
我想你会发现这在C中是不可能的。
C ++有模板和重载,这是解决这类问题的好方法。
在普通的旧C中,您只需为每个需要处理的类型编写不同的函数。
宏是C中的另一个选项,但要考虑它是否值得为其他开发人员带来的努力和困惑。
答案 6 :(得分:2)
您可能需要查看ioctl()
功能。它采用指向内存的通用指针,并根据传递给函数的请求代码对其进行不同的解释。如果没有某些附加信息,您无法确定通用指针指向的内容,而ioctl()
函数则显示了一种(相对简单)的方法。
答案 7 :(得分:1)
我能想到的唯一方法是将类型作为第二个参数传递,或者使用带有指针和枚举的结构或指定类型的结构,并传递它而不是裸指针。 C没有.net和Java这样的内置元数据,甚至不是我所知道的RTTI的等价物。
答案 8 :(得分:1)
这种多角色功能不是推荐的方法,因为很难捕获编程错误和调试。我建议为每个参数类型创建单独的grep函数,并为任何共享的grep代码逻辑调用这些函数。
如果你必须将无类型对象传递给函数,那么我建议你将它们包装在一个用类型装饰它们的结构中。类似的东西:
struct {
enum TYPE { INT, CHAR, STRING } type;
void *object;
}
答案 9 :(得分:1)
不可能。
您必须传递一个额外的变量来告诉函数输入变量的类型。但是我认为你可以使用上面建议的宏。这样你就可以将函数grep分解为3个子函数(如果我可以将它们称为那么)。
如果您稍后传递任何其他数据类型,枚举将更容易。您可以在函数内部使用switch语句并对输入数据执行操作。
enum TYPE( TYPE_1, TYPE_2, TYPE_3,TYPE_MAX}; /*Add other data types into this enum if need be */
请根据您的要求为枚举条目命名。
稍后您可以修改功能开关案例并为其添加其他案例。
答案 10 :(得分:-1)
如果你知道你将要处理的类型,那么你可以为每种类型定义一个grep函数,如:
grep_int(int* pi);
grep_char(char* pc);
grep_float(float* pf);
还要定义像
这样的宏#define GREP(T, TPTR_VAR) grep_##(TPTR_VAR)
因此GREP(int, pi)
之类的通话会转换为grep_int(pi)
答案 11 :(得分:-2)
正如Mark指出的那样,这是不可能的,但你可以为你期望的类型制作重载版本。
编辑:更正,您可以创建类似的功能来处理不同的类型:
void grep_c( char *t )
{
do this
}
void grep_i( int *t )
{
do that
}
我最近写的C ++太多了!