ожидаемые спецификаторы объявления или «...» перед «record_t» в заголовочных файлах c - PullRequest
0 голосов
/ 03 сентября 2018

Я новичок в этих заголовочных файлах в C.

Я пытаюсь использовать makefile для компиляции моих файлов кода вместе. У меня есть 2 заголовочных файла и 2 файла c для каждого заголовка, а также 1 файл main.c.

У меня есть main.c, который является моей основной функцией, и он имеет "#include" dict2.h "". Заголовки dict1 и dict2 несколько совпадают. разница в dict2 имеет дополнительную функцию связанного списка.

-bash-4.1$ make dict1
gcc -Wall -c main.c -o main.o -g
In file included from main.c:6:
dict2.h:1: warning: useless storage class specifier in empty declaration
dict2.h:8: warning: useless storage class specifier in empty declaration
dict2.h:21: error: expected declaration specifiers or '...' before 'record_t'
dict2.h:24: error: expected declaration specifiers or '...' before 'record_t'
dict2.h:42: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
dict2.h:45: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token
dict2.h:48: error: expected ')' before '*' token
make: *** [main.o] Error 1

Моя функция dict2.h выглядит следующим образом:

typedef struct record_t;

typedef struct node_list node_list_t;

struct node_list;

typedef struct list_t;

typedef struct node node_t;

struct node;

node_t* transform_input(FILE *finput, node_t *root);

//line 21
node_t* bst_insert(node_t *root, record_t* data);

//line 24
node_t* bst_create_node(node_t* root, record_t* data);

node_t* bst_search(node_t* root, char* name_keyword, int* numcomparison);

void search_then_print(char* keyword, node_t* root, FILE* foutput, \
   int* numcomparison);

void freeTree(node_t *root);

void print_record(FILE* foutput, node_t* targetnode, char* keyword,\
  int* numcomparison);

//line 42
list_t *insert_at_foot(list_t *list, record_t *datarecord);

//line 45
list_t *create_empty_list(void);

//line 48
void free_list(list_t* list);

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

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

Ответы [ 2 ]

0 голосов
/ 03 сентября 2018

В дальнейшем я использую struct tag против идентификатора типа . Я немного погуглил и нашел (ИМХО) довольно простое объяснение в Википедии .


Некоторые программисты, чувак, упоминали об этом, но, похоже, вы не поняли его точку зрения. Итак, я немного уточню это:

Это действительно:

struct Node {
  struct Node *pNext;
};

и может использоваться с struct:

void insert_after(struct Node *pNode);

Для тех, кому лень набирать struct, всегда может помочь typedef:

struct Node {
  struct Node *pNext;
};
typedef struct Node Node;

Может показаться странным, но компилятор разделяет теги и типы struct в отдельные списки. Таким образом, первый и второй Node не имеют идентификатора "столкновения".

И то, и другое можно сделать одновременно:

typedef struct Node {
    struct Node *pNext;
} Node;

Если предположить другой случай без «рекурсивного» использования типа, тег struct можно даже опустить:

typedef struct {
  int year, month, day;
} Date;

Это тип struct, который может использоваться исключительно без ключевого слова struct.

Я предполагаю, что это было предназначено при написании

typedef struct record_t;

но компилятор интерпретирует это не так, как это может сделать автор. Компилятор читает это как struct с тегом record_t и идентификатором пропущенного типа.

Вот как я читаю

warning: useless storage class specifier in empty declaration

(Полезно знать, что typedef синтаксически обрабатывается в компиляторе, как static и extern и, таким образом, считается классом хранения, хотя это не всем очевидно.)

Я должен признать, что не знаю, как интерпретировать

error: expected declaration specifiers or '...' before 'record_t'

но я бы проигнорировал это и просто исправил бы слабость в typedef (и посчитал бы ошибку последующей ошибкой).

Я также должен признать, что не знаю, как решить эту проблему с помощью анонимного struct и согласиться с идеей struct с тегом, который «повторно используется» в качестве идентификатора типа:

#include <stdio.h>

/* typedef for an incomplete struct */
typedef struct Date Date;

/* use incomplete struct type for prototype of function */
void printDate(Date *pDate);

/* define the complete struct */
typedef struct Date {
  int year, month, day;
} Date;

/* implementation of function */
void printDate(Date *pDate)
{
  printf("%04d/%02d/%02d", pDate->year, pDate->month, pDate->day);
}

/* check this out */
int main(void)
{
  Date date = { 2018, 9, 3 };
  printDate(&date);
  return 0;
}

Выход:

2018/09/03

Демонстрация в реальном времени на ideone

0 голосов
/ 03 сентября 2018

Заявления:

typedef struct record_t;
typedef struct list_t;

скучаю по названию.

Вероятно, должно быть:

typedef struct record record_t;
typedef struct list list_t;
...