access element of struct passed into a void* point

2019-01-26 19:48发布

I'm working with a binary search tree data structure to sort a series of structs with the type definitions:

typedef struct {
    char c;
    int index;
} data_t;

typedef struct node node_t;

typedef node {
    void *data;
    node_t *left;
    node_t *right;
}

The node_t typedef is from a library provided to me for this purpose, presumably with a void* pointer to ensure polymorphism. node will be passed into the function:

static void *recursive_search_tree(node_t *root, void *key, int cmp(void*,void*))

Within the recursive_search_tree function, I want to be able to modify the code to use the index element as a condition to find the match closest to the index of the linear pass over an array of characters, which would ultimately involve a data_t being passed into *key and key->index being accessed within the function.

The Question

Is it possible to access key->index where key is a void* pointing to a data_t struct, or would this only be possible if data_t was declared as the type for key? I have tried to do the latter, however even casting the pointer to an int doesn't seem to pass the compiler.

2条回答
可以哭但决不认输i
2楼-- · 2019-01-26 20:30

Sure it's possible, you'd cast key as type *data_t. (As long as that's really what key points to!)

key                     /* argument of type void* */
(data_t*)key            /* cast as type data_t*   */
((data_t*)key)->index   /* dereferenced */

Here is a simple example:

#include <stdlib.h>
#include <stdio.h>

typedef struct {
    char    c;
    int     index;
} data_t;

typedef struct node {
    void    *data;
    struct node *left;
    struct node *right;
} node_t;

static int cmp(void *lhs, void *rhs)
{
    return ((data_t *)lhs)->index - ((data_t *)rhs)->index;
}

int main(void)
{
    data_t d0;
    data_t d1;

    d0.c     = 'A';
    d0.index = 1;
    d1.c     = 'B';
    d1.index = 2;

    printf("d0 < d1? %s\n", (cmp((void *)&d0, (void *)&d1) < 0 ? "yes" : "no"));
    printf("d1 < d0? %s\n", (cmp((void *)&d1, (void *)&d0) < 0 ? "yes" : "no"));

    return EXIT_SUCCESS;
}
查看更多
Ridiculous、
3楼-- · 2019-01-26 20:38

This is type unsafe, as is any use of void. The use of void is generally because the intermediate is holding onto something it doesn't use for someone else's convenience. This is a C function to let you hold whatever you want in a tree. All it does is return whatever pointer you give it.

In your search function

int cmp(void* dt1, void* dt2)
{
data_t*  data1 = (data_t*)dt1;
data_t*  data2 = (data_t*)dt2;
/* Do what you need with data1 and data2 here */
}

Should let you do whatever you need. The problem you have is you need to cast your values inside the function. The parameters to cmp should exactly match the API for the library you are using, which says void* for the parameters.

查看更多
登录 后发表回答