Ошибка: в C получена ошибка «разыменование указателя на неполный тип» в указателе структуры - PullRequest
3 голосов
/ 11 марта 2011

Привет всем!

Я получил следующую ошибку при попытке проверить код для игры Clever Frog: ошибка: разыменование указателя на неполный тип

«Полный код» находится на pastebin.com - здесь (не истекает). Но я думаю, что с объяснением ниже, любой может понять. Примечание: я еще не реализовал функцию, которая будет стирать выделенную память и другие вещи.

У меня есть структура, определенная в файле 1.c:

#include "1.h"
...
struct test {
   int a;
   };
...

У меня есть 1.h, в котором используется typedef:

...
typedef struct test testT;
...

Тогда у меня есть функция, в которой есть параметр в зависимости от testT, который находится в 2.c:

...
void funcTest(testT **t, int *size, ..){
   /* another function that creates mem.space/alocate memory based enter code here`on the need of size above */
   createMem(t,*size); /* void createMem(testT **t, int size); */

   t[0]->a = 0; /*ERROR HERE*/
   /* ... more code ... */
}
...

Файл 2.h выглядит так:

...
void funcTest(testT **t, int *size, ..);
...

Я пройду testT * var , как указано ниже, в основной программе:

...
testT *varTest; int size;

funcTest(&varTest, &size);
...

Странно то, что код компилируется, когда я использую struct test в файле 1.h (удаление struct test из 1.c - что неправильно). Но при запуске скомпилированной программы именно там, где происходит ошибка, находится место t [0] -> a .

Я уже попробовал «все», но ничего не получалось :( Я верю, что это что-то очень глупое, поэтому, если кто-то что-то знает, пожалуйста, скажите мне: D Спасибо!

Ответы [ 5 ]

5 голосов
/ 11 марта 2011

Когда вы пытаетесь получить доступ к члену a структуры t[0], компилятору необходимо знать, как выглядит эта структура (например, чтобы увидеть, есть ли в ней хотя бы какой-либо член a).Поскольку вы не поместили определение типа struct test нигде, чтобы компилятор мог видеть его при компиляции 2.c, вы получаете ошибку.Компилятор не знает, что содержит struct test.

Если вы поместите определение struct test в 1.h, компилятор увидит, как этот тип выглядит и может использовать члены структуры.

Просто поместите полное определение типа в 1.h, вот где оно должно быть.

3 голосов
/ 11 марта 2011

Где-то у вас есть предварительно обработанный файл с

typedef struct test testT;

, который не включает

struct test {
   int a;
};

Предварительная обработка включает все директивы #include.Если бы вы использовали только указатель testT, компилятор знал бы, что он «выделит память указателя», и компиляция продвинулась бы дальше, чем ожидалось.

Когда вы на самом деле пытаетесь использовать этот указатель дляразыменовывая что-то, компилятор тогда понял бы, что ему НУЖНО полное определение «struct test», и вы получите сообщение об ошибке.

1 голос
/ 11 марта 2011

Определение struct Test видно только внутри файла 1.c.Код t[0]->a не видит, что в этой структуре есть член с именем a.Типы, совместно используемые несколькими компилируемыми модулями, должны быть определены в заголовке!

Вы должны знать, что C / C ++ компилирует каждый файл .c отдельно, поэтому он не может знать, что структура определена в каком-то другом.файл c.

Возможно, вам следует сделать следующее:

(1.h)

struct test {
    int a;
};
...

(1.c)

#include "1.h"
...

(2.c)

#include "1.h"
...
void funcTest(testT **t, int *size, ..){
    createMem(t,*size); /* void createMem(testT **t, int size); */
    t[0]->a = 0;
    /* ... more code ... */
}
1 голос
/ 11 марта 2011

Если вы хотите, чтобы структура могла использоваться как в 1.c, так и в 2.c, она должна быть определена в заголовочном файле, который виден обоим.Я не знаю, почему вы говорите, что это «неправильно», это обычная практика, и у AFAIK нет другого пути к этому напрямую.

Если это определено только в 1.c, то компилятор понятия не имеетесли struct test имеет член с именем "a" при обработке 2.c.

Другой вариант - просто сохранить прямое объявление, как у вас сейчас, но также включить функции доступа / мутатора в заголовок.Тогда 2.c не должен знать о «внутренностях» struct test, но может действовать по нему.Это также очень распространено в API C.

(Вы также можете определить структуру одинаково как в 1.c, так и в 2.c, но это очень плохая идея.)

0 голосов
/ 11 марта 2011

Но при запуске скомпилированной программы именно там, где происходит ошибка, находится место t [0] -> a.

Указатель на выделенную память фактически находится в *t, а не t (как видно из вашего createMatrix кода в Pastebin), поэтому вы действительно должны делать:

(*t)[0].a

и аналогично в цикле for:

(*matriz)[i].row
...