繁体   English   中英

C无效指针问题

[英]C Void pointer question

我在C(嵌入式编程)中有grep函数,它将void指针作为参数。 该函数需要能够处理不同类型的变量,如字符整数和长整数。 我如何编写函数代码,以便它可以自己弄清楚我传递的是什么类型的变量? 我不知道这是否可行。 谢谢

即。


void grep( void *t ) 
{ 
   if( t == char ) 
   { 
      do this 
   } 
   if( t == int ) 
   { 
      do that  
   }  
   ... 
}

任何准确性都无法做到。 例如,4字节整数可以很容易地解释为字符串。 例如,空终止字符串“ABC”将与整数值1094861568相同(取决于字节顺序)。

Void指针只包含存储器中存储数据的位置。 您无法从中推断出任何类型信息。 但你可以做的是,将两个参数传递给你的函数,一个用于类型,另一个用于指针。

如果可以使用C ++,则可以创建一组重载的辅助函数来提供类型信息。

这在C中是不可能的。您必须明确指出参数的预期类型。 您将必须传递第二个参数或传递具有类型信息作为参数的union或struct。

您基本上是在询问如何在C中进行内省 。不幸的是,这不是受支持的功能。

相反,你可以像@ anand.arumug指出的那样使用像grep_char这样的函数。 或者(如果可能的话)您可以转移到C ++并使用其功能重载功能。

直接回答:这是不可能的。 此外,您应该避免编写这样的超级函数,这些函数可以在多种类型上运行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。

我想你会发现这在C中是不可能的。

C ++有模板和重载,这是解决这类问题的好方法。

在普通的旧C中,您只需为每个需要处理的类型编写不同的函数。

宏是C中的另一种选择,但要考虑它是否值得为其他开发人员带来的努力和困惑。

您可能想看看ioctl()函数。 它采用指向内存的通用指针,并根据传递给函数的请求代码对其进行不同的解释。 如果没有某种附加信息,您无法确定通用指针指向的内容,而ioctl()函数则显示了一种(相对简单)的方法。

我能想到的唯一方法是将类型作为第二个参数传递,或者使用指针和枚举的结构或指定类型的结构,并传递它而不是裸指针。 C没有.net和Java这样的内置元数据,甚至不是我所知道的RTTI的等价物。

这种多角色功能不是推荐的方法,因为很难捕获编程错误和调试。 我建议为每个参数类型创建单独的grep函数,并为任何共享的grep代码逻辑调用这些函数。

如果你必须将无类型对象传递给函数,那么我建议你将它们包装在一个用类型装饰它们的结构中。 就像是:

struct {
    enum TYPE { INT, CHAR, STRING } type;
    void *object;
}

不可能。

您必须传递一个额外的变量来告诉函数输入变量的类型。 但是我认为你可以使用上面建议的宏。 这样你就可以将函数grep分解为3个子函数(如果我可以将它们称为那么)。

如果您稍后传递任何其他数据类型,枚举将更容易。 您可以在函数内部使用switch语句并对输入数据执行操作。

enum TYPE( TYPE_1, TYPE_2, TYPE_3,TYPE_MAX}; /*Add other data types into this enum if need be */

请根据您的要求命名枚举条目。

稍后您可以修改功能开关外壳并为其添加一个附加外壳。

如果你知道你将要处理的类型,那么你可以为每种类型定义一个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)

正如Mark指出的那样,这是不可能的,但你可以为你期望的类型制作重载版本。

编辑:更正,您可以创建类似的函数来处理不同的类型:

void grep_c( char *t ) 
{ 
    do this 
}

void grep_i( int *t ) 
{ 
    do that  
}

我最近写的C ++太多了!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM