Невозможно выделить массив Dynami c на C - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь создать структуру графа на C, но у меня есть некоторые проблемы. Во-первых, я получаю 2 ошибки компиляции:

main.c:18:19: error: member reference type 'node' is not a
      pointer; did you mean to use '.'?
      graph[index]->start = NULL;
      ~~~~~~~~~~~~^~
                  .
main.c:18:27: error: expression is not assignable
      graph[index]->start = NULL;
      ~~~~~~~~~~~~~~~~~~~ ^
2 errors generated.
compiler exit status 1

Я не могу понять, что я делаю неправильно. Я пытался создать массив узлов *, но по какой-то причине компилятор не распознает его как указатель. Это как малло c не работает. Кроме того, мне не удается получить доступ к полям * edge, потому что массив узлов * не существует.

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

#define maxNodes 4

typedef struct edge {
    int target;
    struct edge* next;
} edge;

typedef struct {
    edge* start;
} node;

void initializeGraph(node* graph) {
    graph = (node *) malloc(maxNodes * sizeof(node));
    for(int index = 0; index < maxNodes; index++) {
      graph[index]->start = NULL;
    }
}

int main(void) {
    node test;
    initializeGraph(&test);
}

Я пытаюсь инициализировать свою структуру. Любая помощь приветствуется.

Ответы [ 2 ]

1 голос
/ 10 марта 2020

В вашем коротком примере кода есть большое количество проблем. Что касается вашей ошибки, то она покрывается ответом @ dbu sh, а [...] служит разыменованием для вашего указателя, делая оператор '.' (точка) вместо оператора ->.

Далее, вы не можете объявить узел с stati c продолжительностью хранения в main() и передать его адрес для распределения в вашей функции. Когда вы объявляете node test; все хранилище уже предоставлено в стеке. Затем вы не можете передать этот адрес своей функции и выделить дополнительную память для этой структуры.

Если вы хотите иметь более одного узла, вы можете объявить массив с помощью stati c продолжительность хранения в main(), или вы должны объявить указатель в main() и выделить его в своей функции. Чтобы сделать это распределение видимым в main(), как отмечено в моем комментарии, вы можете либо (1) сделать тип возврата node * и вернуть указатель на выделенный блок для назначения в вызывающей стороне, либо (2) сделать параметр node** и передайте адрес вашего указателя в качестве параметра.

Если сложить это вместе и выбрать параметр (1) выше, вы можете сделать:

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

#define maxNodes 4

typedef struct edge {
    int target;
    struct edge* next;
} edge;

typedef struct {
    edge* start;
} node;

node *initializeGraph (void) {
    node *graph = malloc(maxNodes * sizeof *graph);
    if (!graph)
        return NULL;
    for (int index = 0; index < maxNodes; index++) {
        graph[index].start = NULL;
    }
    return graph;
}

int main (void) {

    node *test = initializeGraph();

    if (!test)
        fputs ("error: initialization failed.\n", stderr);
    else
        puts ("initialization succeeded");
}

Пример Use / Вывод

$ ./bin/graphinit
initialization succeeded

Распределение для каждого теста [i] .start

Прежде чем вы сможете использовать любой из указателей start, вы должны выделите память для struct edge и назначьте начальный адрес для этого блока памяти каждому из ваших test[i].start указателей. Вы можете сделать это в той же функции initializeGraph(), указав, где вы в данный момент устанавливаете указатели NULL, например,

node *initializeGraph (void)
{
    node *graph = malloc(maxNodes * sizeof *graph);
    if (!graph)
        return NULL;
    for (int index = 0; index < maxNodes; index++) {
        graph[index].start = malloc (sizeof *graph[index].start);
        if (!graph[index].start)
            return NULL;
    }
    return graph;
}

. Затем вы можете назначить значение для target в каждом. Расширяя предыдущий пример, вы могли бы сделать:

int main (void) {

    node *test = initializeGraph();

    if (!test)
        fputs ("error: initialization failed.\n", stderr);
    else
        puts ("initialization succeeded");

    for (int i = 0; i < maxNodes; i++)
        test[i].start->target = i;

    puts ("targets filled");
}

Пример Использование / Вывод

$ ./bin/graphinit
initialization succeeded
targets filled

(не забудьте освободить память, выделенную при этом больше не нужен)

Посмотрите вещи и дайте мне знать, если у вас есть дополнительные вопросы.

0 голосов
/ 10 марта 2020

Оператор индекса массива [] неявно разыменовывает указатель. Синтаксис a[b] точно такой же, как и *(a + b).

. Это означает, что graph[index] имеет тип node, а не node *. Поэтому используйте . вместо ->, как показано в сообщении об ошибке.

graph[index].start = NULL;
...