我们可以使用数组的void指针

时间:2014-03-24 04:28:54

标签: c

我正在研究一个自由函数,在这个函数中我们为学生和书定义了我们自己的数据类型我必须编写一个代码,通过id和book来查找学生这两个函数。在这个函数中,我传递的指针是不同的,但逻辑是相同的,所以我得到了一个,但为什么我们不能写一个函数并传递我们想要的东西。我的意思是当我们通过学生列表时,它将返回学生的索引,当我们通过书籍列表时,它将返回书籍的书籍索引。我们可以使用void指针吗???谢谢大家!!!

int findBookId(Book* booklist,int* bcount,unsigned int* tbid)
{
    int i;
    for (i=0; i<*bcount; i++)
    {
        if (booklist[i].id==*tbid)
        {
            return i;
        }
    }
    return NOT_FOUND;
}

int findStuId(Student* stulist,int* scount,unsigned int* tsid)
{
    int i;
    for (i=0; i<*scount; i++)
    {
        if (stulist[i].id==*tsid)
        {
            return i;
        }
    }
    return NOT_FOUND;
}   

4 个答案:

答案 0 :(得分:1)

假设你有一个student结构:

struct student {
    int id;
    char name[20];
};

您可以模仿qsort()功能,设计参数以接收回调函数,并在您使用void *时接收每个元素的大小和大小。

int find_ele(void *base, size_t num, size_t width,
    int (*equal)(const void *, const void *),
    void *param)
{
    int i;

    for (i = 0; i < num; ++i) {
        if (equal((char *) base + i * width, param)) {
            return i;
        }
    }

    return -1;
}

然后,定义一个&#34;测试员&#34;:

int student_tester(const void *p1, const void *p2)
{
    struct student *sp = (struct student *) p1;
    int id = *(int *) p2;
    return sp->id == id;
}

main()函数中:

int main(void)
{
    struct student student_list[] = {
        0, "A",
        1, "B",
        2, "C"
    };

    int id = 2;
    int index = find_ele(student_list, sizeof student_list,
        sizeof(struct student), student_tester, &id);
    if (index != -1) {
        printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
            index, student_list[index].name);
    } else {
        printf("Not found. \n");
    }

    return 0;
}

这有点复杂。如果您不在乎,可以创建宏来简化它。

find_ele重命名为_find_ele,然后创建一个宏:

#define find_ele(base, num, compare, param) _find_ele(base, \
    num / sizeof base[0], \
    sizeof base[0], \
    compare, param)

创建另一个宏来定义&#34;测试员&#34;:

#define define_tester(name, type, type_to_find, code) \
    int name(const void *_p, const void *param) { \
        type *p = (type *) _p; \
        type_to_find value = *(type_to_find *) param; \
        return (code); \
    }

现在你可以定义一个&#34;测试员&#34;像这样:

define_tester(student_tester, struct student, int,
    p->id == value);

完整代码:

#include <stdio.h>

int _find_ele(void *base, size_t num, size_t width,
    int (*equal)(const void *, const void *),
    void *param)
{
    int i;

    for (i = 0; i < num; ++i) {
        if (equal((char *) base + i * width, param)) {
            return i;
        }
    }

    return -1;
}

#define find_ele(base, num, compare, param) _find_ele(base, \
    num / sizeof base[0], \
    sizeof base[0], \
    compare, param)

#define define_tester(name, type, type_to_find, code) \
    int name(const void *_p, const void *param) { \
        type *p = (type *) _p; \
        type_to_find value = *(type_to_find *) param; \
        return (code); \
    }

struct student {
    int id;
    char name[20];
};

define_tester(student_tester, struct student, int,
    p->id == value);

int main(void)
{
    struct student student_list[] = {
        0, "A",
        1, "B",
        2, "C"
    };

    int id = 2;
    int index = find_ele(student_list, sizeof student_list, student_tester, &id);
    if (index != -1) {
        printf("find_ele(id=2) = student_list[%d]; name = %s. \n",
            index, student_list[index].name);
    } else {
        printf("Not found. \n");
    }

    return 0;
}

答案 1 :(得分:0)

是的,你可以使用void指针,如果你试图存储你的数组的地址..你的数组可能包含整数类型或存储的其他一些数据类型,它没关系,但在取消引用void指针时进行类型转换很重要。

答案 2 :(得分:0)

是的,您可以使用void*,但在取消引用时您应该知道指针的确切type
因此,当您可以使用您的功能时,请添加另一个参数:

type = 0 for Books
     = 1 for students 

然后你的功能变为:

int findId(void* list,int* count,unsigned int* tbid, int type)
{
    Book* booklist=NULL;
    Student* stulist=NULL;
    int i;
    if(type===0)
         booklist = (Book*) list;
    else if(type==1)
         stulist = (Student*) list;
    else
         // Handle this undefined case

    // And now use the same type variable to decide which pointer to use to match the values
    . . . . 
}

答案 3 :(得分:0)

我认为你不能在这些功能中使用void*

如果您将功能更改为1并创建了类似的内容:

int findObjId(void* objlist,int* count, unsigned int* objid)
{
    int i;
    for (i=0; i<*scount; i++)
    {
        if (objlist[i].id==*objid)
        {
            return i;
        }
    }
    return NOT_FOUND;
}   

您将无法从objlist中提取数据。 *objlistobjlist[i]都不能被解除引用以评估对象。编译器肯定会阻止你使用任何这样的语句。

如果您有选项,请切换到C ++。使用模板,您可以毫不费力地实现目标。