Корректные имена, но «разыменование указателя на неполный тип» - PullRequest
0 голосов
/ 28 мая 2019

Я застрял с этой ошибкой:

cities.c: In function ‘main’:
cities.c:7:48: error: dereferencing pointer to incomplete type ‘struct Graph’
  printf("well, it got here. nodeCount: %d\n", x->nodeCount);

Все остальные решения указывают на то, что имена написаны с ошибками и, следовательно, не определены, однако, если я переместу определение struct Graph в заголовок, оно будет работать просто отлично.

Ранее я использовал эту механику в моей другой библиотеке, и она все еще прекрасно компилируется, я часами пытался передвигать вещи безрезультатно.

graph.h:

#ifndef GRAPH_H
#define GRAPH_H

typedef struct Graph * Graph;

int graphCreate(Graph*, int);
int graphAddPath(Graph, int, int, unsigned int);
int graphRemovePath(Graph, int, int);
int graphDestroy(Graph*);

#endif /* GRAPH_H */

graph.c: https://pastebin.com/FzkaJJwP

towns.c:

#include "graph.h"
#include <stdio.h>

int main() {
    Graph x;
    graphCreate(&x, 5);
    printf("well, it got here. nodeCount: %d\n", x->nodeCount);
}

Вывод, как и ожидалось, в моей библиотеке на https://git.mif.vu.lt/emiliskiskis/c_deck.

Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 28 мая 2019

Сообщение компилятора довольно ясно.Тип является неполным, что в основном означает, что компилятор знает только, что существует структура с именем Graph, но он не знает, как он выглядит.Следствием этого является то, что вы не можете получить доступ к полям.

Итак, сначала вы должны ответить на этот вопрос.Хотите ли вы, чтобы программист, использующий библиотеку, имел доступ к полям Graph?Если нет, поместите определение в файл .c.Если да, поместите определение в файл .h.

Еще одна вещь, которую следует учитывать, - typedef struct Graph * Graph.Вы скрываете очень много информации при определении типа структуры, и то же самое относится и к типу определения указателя.Теперь вы делаете оба.Мое личное мнение таково, что вам действительно следует избегать этого, если только ответ на поставленный выше вопрос не является «нет».

Я предлагаю, если вы хотите, чтобы пользователь библиотеки имел доступ к полямstruct Graph, полностью удалите typedef.Если вы хотите скрыть это от пользователя, используйте функции доступа к коду, например:

// cities.h
int getNodeCount(Graph g);
// cities.c
int getNodeCount(struct Graph * g) {
    return g->nodeCount;
}

И используйте это так:

Graph g;
int nodeCount = getNodeCount(g);

Обратите внимание, что я НЕиспользуйте typedef в определении функции.Только в его прототипе.

0 голосов
/ 28 мая 2019
  1. Определение struct Graph содержится в файле graph.c. При компиляции файла cities.c это определение не отображается. Вам нужно переместить определение в graph.h

    struct Graph {
       unsigned int **matrix;
       int nodeCount;
    };
    
  2. Как предполагает Блейз, приведенное ниже определение сбивает с толку. typedef struct Graph * Graph. Лучшим решением было бы

    typedef struct Graph Graph;
    

и затем в коде вы можете использовать

int graphCreate(Graph **, int);
int graphAddPath(Graph *, int, int, unsigned int);
int graphRemovePath(Graph *, int, int);
int graphDestroy(Graph **);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...