简体   繁体   中英

Can we use void pointer of arrays

I am just working on a liberty functions in which we define our own datatypes for student and book I have to write a code which finds student by id and book by id these are the two functions. In this functions the pointers which I pass are different but the logic is the same so I got a though that why can't we write one function and pass which thing we want. I mean when we pass the student list it will return the index of student when we pass the book list it will return the book index of the book. Can we use void pointers for that??? Thank you everyone!!!

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

Assuming you have a student structure:

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

You can imitate qsort() function, to design a parameter to receive a callback function and to receive the size and size of each element if you'd like use 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;
}

Then, define a "tester":

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

In main() function:

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

This is a bit complicated. You can create macros to simplify it if you don't care.

Rename find_ele to _find_ele , and create a macro:

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

And create another macro to define a "tester":

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

Now you can define a "tester" like this:

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

Complete code:

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

是的,如果您试图存储数组的地址,则可以使用void指针。您的数组可能包含整数类型或其他存储的数据类型,这并不重要,但是在取消引用void指针时进行正确的类型转换很重要。

Yes you can use void* , but while dereferencing you should know the exact type of the pointer.
So, when you can your function, add another parameter:

type = 0 for Books
     = 1 for students 

And then your function becomes:

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
    . . . . 
}

I don't think you can use void* in these functions.

If you changed your functions to one and created something like:

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

you won't be able to extract the data from objlist . Neither *objlist , nor objlist[i] can be dereferenced to evaluate to an object. The compiler will definitely stop you from using any such statement.

If you have the option, switch to C++. Using templates, you can accomplish your goal without breaking a sweat.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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