C - (void *) в int - PullRequest
       35

C - (void *) в int

4 голосов
/ 16 февраля 2011

Я реализую простую очередь приоритетов в C для ядра, и поэтому я не могу использовать какие-либо стандартные библиотеки. Очередь содержит головной узел, и каждый узел указывает на следующий в очереди.

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

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

Как видите, каждый узел хранит свои данные в пустоте *. У меня возникли проблемы с преобразованием этих данных, скажем, int, когда я вытаскиваю данные из стека.

//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);

Почему я не могу получить исходное значение здесь? Кажется, я печатаю значение указателя. В качестве альтернативы, есть ли лучший способ справиться с этим?

== изменить (извините, я должен был включить их):

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

Ответы [ 4 ]

4 голосов
/ 16 февраля 2011

Ваш код все в одной функции?Если нет, то int int_data выталкивается из стека (не из вашей очереди, а из фактического стека), поэтому, вероятно, вы печатаете мусор;Вы храните адрес локальной переменной.

Я бы предложил изменить void* data на int data.(Если вам нужно, вы можете сохранить адрес в int и позже преобразовать его в указатель.)

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

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

После повторного просмотра кода у вас возникла та же проблема при добавлении нового узла,node new выпадает из области видимости в конце функции, поэтому в основном все ваши узлы в очереди указывают на недопустимую память.

3 голосов
/ 16 февраля 2011

Если операция «pop» выполняется в другой функции:

Возможно, проблема в том, что вы помещаете локальную переменную в свою очередь.

Когда вы переходите к pop,адрес больше не действителен (или, по крайней мере, не указывает на значение int), поэтому вы печатаете что-то странное.Поскольку данные больше не указывают на ваш int, они, вероятно, выглядят как адрес памяти.

0 голосов
/ 16 февраля 2011

Вы можете использовать макрос glib GPOINTER_TO_INT :

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

Но, пожалуйста, примите к сведению с примечанием к документу:

ВЫ НЕ МОЖЕТЕ ХРАНИТЬ ТОЧКИВ ИНТЕГРАХ.ЭТО НЕ ПОРТАТИВНО В ЛЮБОМ ФОРМЕ ИЛИ ФОРМЕ.Эти макросы ТОЛЬКО позволяют хранить целые числа в указателях и сохранять только 32 бита целого числа;значения за пределами диапазона 32-разрядного целого числа будут искажены.

0 голосов
/ 16 февраля 2011

вы устанавливаете data = int_data (т.е. int -> void *) или data = &int_data (т.е. int * -> void *)? В первом случае вы должны написать printf("pop data (100): %d\n", pop_data);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...