Простая путаница видимости файла заголовка в C - PullRequest
1 голос
/ 17 декабря 2011

У меня странная проблема в C, связанная с включением заголовочных файлов.

main.c

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

int waste_new_line();

int main()
{
    location *crossroads = malloc(sizeof(*crossroads));
...

location.h

typedef struct Location_Struct location;

location.c

typedef struct Location_Struct {
    int ID;
    char *name;
    char *description;
} location;

int setup_location(location* l, char* name)
{
    ...

Теперь это не работает, потому что

location *crossroads = malloc(sizeof(*crossroads));

выдает ошибку: разыменование указателя на неполноеtype означает, что он может видеть содержимое location.h, но, похоже, он не знает о location.c ...

Я посмотрел вокруг, и все учебники, которые я видел, говорят, чтокомпоновщик свяжет оба файла вместе.

РЕДАКТИРОВАТЬ:

Я изменил код, чтобы включить инициализатор внутри location.c следующим образом:

main.c

...
#include "location.h"

int waste_new_line();

int main()
{

    location *crossroads = initialize_location();
    ....

location.h

typedef struct Location_Struct location;

location* initialize_location();

location.c

...
typedef struct Location_Struct {
    int ID;
    char *name;
    char *description;
} location;

location* initialize_location(location* l)
{
    return malloc(sizeof(location));
}
...

Этопо-прежнему выдает ту же ошибку, но только когда я пытаюсь получить доступ к членам перекрестка, используя:

crossroads->description

, это приведет к отклонению в неполный тип ошибка.

РЕДАКТИРОВАТЬ 2: сейчас я решилпросто поместить определение структуры в заголовочный файл ...

Ответы [ 3 ]

4 голосов
/ 17 декабря 2011

Такое поведение ожидается.Когда вы #include "location.h", компилятору виден только заголовочный файл.Файл location.c появляется позже, во время ссылки.

У вас есть два варианта:

  1. Добавить функцию, которую вы объявляете в location.h и определяете в location.c, который делает необходимое malloc и возвращает указатель.
  2. Перемещает полное определение структуры в файл заголовка.
2 голосов
/ 17 декабря 2011

Файл main знает о struct, называемом Location_Struct (и typedef). Он понятия не имеет, насколько он велик, поэтому вы не можете применить sizeof к нему.

Поскольку вы эффективно скрываете макет и реализацию Location_Struct, имеет смысл предоставить «конструктор», который его выделяет.

EDIT

Кажется, я должен упомянуть, что под "конструктором" я подразумеваю обычную функцию, которая имеет доступ к реализации структуры и может выделять и, возможно, предварительно заполнять объект.

1 голос
/ 17 декабря 2011

Вам нужно поместить определение Location_Struct в файл заголовка location.h.Компилятор не «видел» другой исходный файл (если бы он не был # include'd, что обычно не было бы хорошей идеей).

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