2017-02-08 16 views
0

Мне не хватает понимания указателей здесь. foo1 является указателем типа foo. В dequeue есть список элементов типа foo, которые динамически выделяются в очереди queueList. Моя миссия состоит в том, чтобы получить foo1, чтобы указать на голову очереди, однако, доступ к указателю foo1, который был принят в DEQUEUE() с * данные вызывает Segfault. Здесь мне не хватает понимания. Is * данные не относится к foo1 Указатель?Segfault при разыменовании void ** аргументы

struct foo 
{ 
//Properties Here 
}; 

int main() 
{ 
    struct foo* foo1; 
    dequeue(myQueueList, (void*) foo1); 
} 

void dequeue(struct queue* queueList, void **data) 
{ 
    *data = NULL; //Causes Seg fault if I do this too 
    *data = queueList->head->data; //Seg fault if I do this as well 
    return; 
} 

Моя очередь определяется как:

struct queue 
{ 
    node * head; 
    //other stuff 
}; 

struct node 
{ 
    void * data; 
    //other stuff 
}; 

Edit: foo1 не инициализируется в основной. Я хочу инициализировать его в dequeue, установив его равным другому указателю struct foo *, который был установлен в очередь.

Edit2: queue содержит список указателей struct foo *.

Редактирование 3: благодаря wildplasser, он исправлен с (void *) foo1 -> (void *) & foo1. Но почему я должен использовать & foo1, а не (void *)?

+2

'dequeue (myQueueList, (void *) foo1);' - >> 'dequeue (myQueueList, &foo1);' Также: ваш указатель * foo1 указывает нигде, нет объекта foo, на который он указывает, и это а не NULL. – wildplasser

+0

@wildplasser Почему NULL необходимо для foo1, когда foo1 инициализируется в dequeue? Что я хочу, это foo1, чтобы указать на другой тип foo в куче. Или я думаю об этом неправильно? Я хочу, чтобы эквивалент: struct foo * foo1 = queueList-> head-> data; где данные являются типом void *. –

+0

является 'queueList-> head-> data' a' struct foo * 'тип маскировки как' void * '? – yano

ответ

2

В этом коде:

struct foo* foo1; 
dequeue(myQueueList, (void*) foo1); 

выражение (void *)foo1 вызывает неопределенное поведение, потому что вы используете значение неинициализированного указателя.

Понятие о том, что вы хотели сделать, чтобы передать адресfoo1 функции, так что функция может изменить foo1. Вам нужен оператор &, чтобы найти адрес вещей.

Однако функция ничего не знает о struct foo *. void ** не является общим типом указателя; это указатель точно на void * и ничего больше. Таким образом, чтобы сделать этот код работать без изменения определения dequeue, что вам нужно сделать void * переменную:

void *vfoo; 
dequeue(myQueueList, &vfoo); 
struct foo *foo1 = vfoo; 

Было бы проще использовать dequeue, если вы могли бы изменить его конструкцию; в частности, вернуть его void *. Тогда вы можете написать struct foo *foo1 = dequeue(myQueueList);.

Примечание: в комментариях было предложено использовать dequeue(myQueueList, (void **)&vfoo);, однако это приведет к неопределенному поведению из-за строгого нарушения псевдонимов. Объект типа struct foo * не может быть доступен через lvalue типа void *.

+0

Вижу, поэтому я просто хочу уточнить. Передача в '(void *) foo1' для arg2 эквивалентна передаче' * foo1', если foo1 был типом void? И когда я передаю '& foo1 ', я передаю' ADDRESS' 'POINTER', который можно отменить в указателе, используя' * data' внутри моей функции 'dequeue'. И для 'struct foo * foo1 = vfoo;' Почему мы не будем вводить cast 'vfoo' в (struct foo *) vfoo, если мы это сделаем? Я согласен, что было бы проще использовать dequeue, если мы изменим дизайн, но мне был предоставлен заголовочный файл моего профессора, который мы не можем изменить для этого задания. –

+0

Какое неопределенное поведение забрасывало бы 'foo1' в' (void *) 'или' (void **) 'причина? И как 'dequeue()' видит foo1 in '(void **) & foo1' versus' (void *) & foo1', когда передается для arg2? –

+0

@TommySaechao Re. второй комментарий, я объясняю это в своем ответе. Использование значения неинициализированного указателя вызывает неопределенное поведение. Использование указателя использует его значение. '(void *) & foo1' и' (void **) & foo1', как аргумент функции, имеют тот же эффект, поскольку прототип функции гарантирует, что первая будет преобразована в последнюю. –