简体   繁体   中英

C — (void*) to int

I'm implementing a simple priority queue in C for a kernel and so I can't use any standard libraries. The queue holds a head node and each node points to the next in the queue.

typedef struct node node;
struct node {
    node *next;
    void *data;
};

typedef struct  {
    node *head;
    int n;
} queue;

As you can see, each node holds it data in a void*. I'm having trouble converting this data to lets say an int when I pop the data off the stack.

//push data
int int_data = 100;
push(q, &int_data);
//...
//pop data
node* popped = pop(q);
int *pop_data = popped->data;
printf("pop data (100): %d\n", *pop_data);

Why can't I get the original value here? I seem to be printing a pointer value. Alternatively, is there a better way to handle this?

== edit (sorry should have included these):

void push(queue *q, void *data)
{
    node new;
    new.data = data;
    node *new_ptr = &new;

    if(is_empty(q))
    {
        q->head = new_ptr;
        q->n++;
        return;
    }

    int i;
    node *curr = q->head;
    for(i=0; i<q->n; i++)
    {
        curr = curr->next;
    }
    curr->next = new_ptr;
    q->n++;
}

node* pop(queue *q)
{
    node *curr = q->head;
    q->head = curr->next;
    return curr;
}

Is your code all in one function? If not, int int_data is getting popped off the stack (not your queue, the actual stack) which is probably why you are printing garbage; you are storing the address of a local variable.

I would suggest changing void* data to int data . (If you need to, you can store an address in an int and can cast it back to a pointer later.)

int int_data = 100;
push(q, int_data);

node* n = pop(q);
int num = n->data;

After reviewing your code again, you have the same problem when adding a new node. node new falls out of scope at the end of the function, so basically all of your nodes in your queue are pointing to invalid memory.

If the "pop" operation is in a different function:

The problem is likely because you're pushing a local variable into your queue.

When you go to pop, this address is no longer valid (or at least not pointing to an int value), so you're printing something strange. As the data is no longer pointing to your int, it probably looks like a memory address.

are you setting data = int_data (ie int --> void*) or data = &int_data (ie int* --> void *) ? In the former case, you have to write printf("pop data (100): %d\\n", pop_data);

You can use the glib GPOINTER_TO_INT macro:

#define GPOINTER_TO_INT(p) ((gint)  (glong) (p))

But please, take note with the doc note:

YOU MAY NOT STORE POINTERS IN INTEGERS. THIS IS NOT PORTABLE IN ANY WAY SHAPE OR FORM. These macros ONLY allow storing integers in pointers, and only preserve 32 bits of the integer; values outside the range of a 32-bit integer will be mangled.

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