Круговая зависимость в одном заголовочном файле C. Предварительная декларация нужна? - PullRequest
0 голосов
/ 22 июня 2019
#ifndef STAGE_TABLE_DEFINITION_HEADER
#define STAGE_TABLE_DEFINITION_HEADER

typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);

typedef struct {
    const char* stage_name;
    stage_table_function_t* function;
} stage_t;

typedef struct {
    uint32_t error_number;
    stage_t* current_stage;
} stage_table_context_t;

#endif 

Получение ошибки неизвестного типа на stage_table_context_t.

Указатель функции stage_table_function_t относится к stage_table_context_t, а stage_table_context_t относится к stage_table_function_t.

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

Извиняюсь за глупый вопрос, я был вдали от C в течение 6 месяцев, и у меня был небольшой пердеж.

edit: исправлены некоторые опечатки в коде.

Ответы [ 2 ]

4 голосов
/ 22 июня 2019

Вы можете сделать объявление struct перед его определением:

/* declaration */
struct foo;

.....

/* definition */
struct foo
{
   ....
};

Везде, где вы пишете struct foo - это объявление структуры, поэтому вам не нужно помещать ее вВ отдельной строке вы можете указать это в typedef, объявлении указателя и т. д. Просто учтите, что иногда, как и в объявлениях переменных типа struct foo, вам также необходимо определение (для вычисления размера переменной);

/* declare struct foo ..*/   
struct foo;

/* .. or declare struct foo ..*/   
typedef struct foo foo;

/* .. or declare struct foo ..*/   
struct foo *p;   

/* .. or declare struct foo */   
int bar (struct foo *p);  

/* Not valid since we don't have definition yet */
struct foo f1;   

/* definition */
struct foo
{
   ....
};

/* Valid */
struct foo f2;   

В вашем случае вы не дали структуре имя;вы только что создали typedef, который является псевдонимом для анонимной структуры.Итак, чтобы объявить вашу структуру вперёд, вы должны дать ей имя:

/* 
  forward declare the `struct stage_table_context_t` and give it a typedef alias
  with the same name as the structs name
*/ 
typedef struct stage_table_context_t stage_table_context_t;

typedef stage_table_context_t* (*stage_table_function_t)(stage_table_context_t*);

typedef struct {
    const char* stage_name;
    stage_table_function_t* function;
} stage_t;

struct stage_table_context_t{
    uint32_t error_number;
    stage_t* current_stage;
} stage_table_context_t;
4 голосов
/ 22 июня 2019

Вы просто должны сообщить компилятору, что stage_table_context_t должно быть struct; тем самым вы неявно объявляете struct stage_table_context_t, фактическое определение которого может появиться позже. Обратите внимание, что typedef не определяет struct, он просто вводит псевдоним. Таким образом, фактическое определение - struct stage_table_context_t { ..., независимо от того, введен ли для него псевдоним или нет (и независимо от того, какое имя вы используете для псевдонима).

typedef struct stage_table_context_t* (*stage_table_function_t)(struct stage_table_context_t*);

typedef struct {
    const char* stage_name;
    stage_table_function_t* function;
} stage_t;

struct stage_table_context_t {
    uint32_t error_number;
    stage_t* current_stage;
};

// optional (if you want to use "stage_table_context_t" as an alias for "struct stage_table_context_t"):
typedef struct stage_table_context_t stage_table_context_t;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...