Как отложить указатель на указатель на кучу? - PullRequest
2 голосов
/ 10 апреля 2019

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

. По какой-то причине у меня возникает ошибка сегментации при разыменовании от e до List:

struct ELEMENT{
    int key;
    int edge;
    struct ELEMENT *adjList;
};

int numOfNodes = 3; 

struct ELEMENT *e = (ELEMENT*)malloc(numOfNodes * sizeof(struct ELEMENT));
// e is now on the heap

struct ELEMENT **List = (ELEMENT**)malloc(numOfNodes * sizeof(struct ELEMENT));
// List (pointer to e) is now on the Heap

List[1]->key = 5;  // segmentation fault occurs here

Ответы [ 3 ]

1 голос
/ 10 апреля 2019

Как уже заметили другие, вам не нужна секунда malloc. Вы просто хотите, чтобы List указывал на e, поэтому все, что вам нужно, это назначить "адрес" e на list.

struct ELEMENT **List = &e;

Кроме того, неправильный способ доступа к элементам с помощью List. Посмотрите на это так:

  • e[n] получит доступ к struct ELEMENT по индексу n

  • *List - это то же самое e

  • Таким образом, для доступа к элементам в массиве вам потребуется (*List)[n]

  • и для доступа к члену вам понадобится (*List)[n].key

Кстати: никто из ваших ... malloc.... не может скомпилировать, поскольку вы забыли struct в актерском составе, но вместо добавления struct просто удалите этот акт. Как:

struct ELEMENT *e =  malloc(numOfNodes * sizeof *e);
                    ^                           ^^
                no cast                    use dereferenced pointer to calculate size

С этими изменениями ваш полный код будет:

struct ELEMENT{
    int key;
    int edge;
    struct ELEMENT *adjList;
};

int numOfNodes = 3; 

struct ELEMENT *e = malloc(numOfNodes * sizeof *e);
struct ELEMENT **List = &e;
(*List)[1].key = 5;
0 голосов
/ 10 апреля 2019

С этой строкой

struct ELEMENT *e = (struct ELEMENT*)malloc(numOfNodes * sizeof(struct ELEMENT));

вы не просто выделяете память для переменной struct ELEMENT, но создаете массив размером 3 и набираете struct ELEMENT.

Но, как я понимаю, по вашему коду вы хотите создать список и добавить переменную e. Это можно сделать вот так

struct ELEMENT **List = malloc(numOfNodes * sizeof(struct ELEMENT*));   //This allocate memory for 3 pointers, List[i] is type struct ELEMENT *

После того, как вы можете выделить память для каждого указателя следующим образом

int i;
for(i = 0; i < numOfNodes; i++)
{
    List[i] = malloc(sizeof(struct ELEMENT));   //here allocate memory for each pointer, for now each List[i] is type struct ELEMENT
}

То есть можно изменить объявление e на struct ELEMENT *e = malloc(sizeof(struct ELEMENT));

и используйте e как хотите, например

e->adjList = NULL;
e->edge = 5;
e->key = 15;

И добавить его к List

List[i] = e;

Если вы просто хотите, чтобы указатель ссылался на переменную e, вы можете использовать struct ELEMENT **List = &e; или более простой struct ELEMENT *p_elem = e;. Таким образом, вы можете использовать эти указатели для изменения значения e членов.

Не забудьте free память, которая была выделена ранее.

Надеюсь, это решит все ваши выводы.

0 голосов
/ 10 апреля 2019

Если List должен указывать на e, то вам не следует снова звонить malloc().Вы должны сделать:

struct ELEMENT **List = &e;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...