C: Предварительное объявление typedef, которое будет определено позже для использования при объявлении функции сейчас

Так.. У меня что-то вроде курицы и яйца.

У меня есть Controller_setup.h и Equipment_setup.h, которые используют определения типов, определенные в другом. Я мог бы много писать здесь об обосновании того, почему это так, но воздержусь от этого, если только кто-то действительно не хочет знать (хотя в основном это была попытка заставить код в Equipment_setup.c/h работать с различными системами контроллера, просто имея другой Controller_setup.h).

На предыдущем контроллере и компиляторе (контроллер использовал процессор ARM, а мы использовали компилятор IAR и IDE) мы разработали код, и я смог перенаправить объявление/переопределение typedefs, и это сработало. Это даст нам много предупреждений, но оно будет компилироваться и работать.

Теперь, когда мы на самом деле пытаемся перенести на другой контроллер, используя другую IDE и компилятор (контроллер использует процессор TriCore, а мы используем IDE Code::blocks с компилятором GNU GCC для TriCore V3.4.6), он теперь вызывает ошибки и выигрывает. пусть код компилируется.

Я очень новичок в этом, но из того, что я понял, я должен иметь возможность в любое время поместить объявление о том, что этот тип данных определен где-то, поэтому компилятор не должен беспокоиться, когда я ссылаюсь на этот тип данных в моих объявлениях функций.

Поскольку он работал на одном компиляторе (правда, с предупреждениями), я надеюсь, что теперь есть какой-то способ заставить его работать. Я не думаю, что это что-то столь же простое, как использование другого синтаксиса, не так ли? Можно ли объявить typedef вместо его переопределения?

На самом деле я только что загуглил этот точный вопрос, и, следуя этому следу, я, кажется, теперь понимаю, что то, что я хочу сделать, разрешено в соответствии с C11, но не в предыдущих стандартах C. Насколько я могу судить, компилятор Tricore не поддерживает C11, поэтому, вероятно, раньше он работал, а сейчас нет.

Но если кто-то может помочь проверить это понимание, это будет оценено.

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

Ниже приведена упрощенная версия того, что работало, но не сейчас. Я пропустил части, где Controller_setup.h ссылается на Equipment_setup.h. Когда проект построен, сначала читается Equipment_setup.h, поэтому я получаю сообщение об ошибке при чтении переопределения в Controller_setup.h.

Сообщение об ошибке:

  • error: [12993] redefinition of typedef 'IO_link_t'
  • error: [13256] previous declaration of 'IO_link_t' was here

Equipment_setup.h

//The functions declared here are used by other .c files which
//determine how the equipment is to operate

typedef enum IO_devices_t IO_devices_t;
typedef struct IO_link_t IO_link_t;

//Declare function for checking status of a given IO device
uint8_t check_IO_device_status(IO_device_t device);

//Declare function for calibrating an input
uint8_t calibrate_input(IO_link_t*  input);

Controller_setup.h

typedef enum IO_devices_t{
  MAIN_CONTROLLER,
  REMOTE_IO_1,
  REMOTE_IO_2,
  //... will vary based on controllers being used...
  HMI_1,
  NUMBER_IO_DEVICES
} IO_devices_t;

typedef struct IO_link_t {
  IO_msg_ptr_t          IO_msg_ptr;
  uint8_t               IO_msg_size;
  IO_logic_ptr_t        IO_logic_ptr;
  //... other members as required by Equipment_setup.h ...
  //... members that vary based on the controller's SDK ...
} IO_link_t;
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
185
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы делаете это:

typedef struct IO_link_t IO_link_t;

Тип typedefопределяет. Вы также объявлениеstruct IO_link_t. Когда вы затем сделаете это:

typedef struct IO_link_t {
  IO_msg_ptr_t          IO_msg_ptr;
  uint8_t               IO_msg_size;
  IO_logic_ptr_t        IO_logic_ptr;
  //... other members as required by Equipment_setup.h ...
  //... members that vary based on the controller's SDK ...
} IO_link_t;

Вы определятьstruct IO_link_t, который ранее не был определен, но вы также переопределить тип IO_link_t. Вот откуда ошибка. То же самое касается enum.

Вы можете исправить это, удалив typedef в точке определения struct и enum.

enum IO_devices_t{
  MAIN_CONTROLLER,
  REMOTE_IO_1,
  REMOTE_IO_2,
  //... will vary based on controllers being used...
  HMI_1,
  NUMBER_IO_DEVICES
};

struct IO_link_t {
  IO_msg_ptr_t          IO_msg_ptr;
  uint8_t               IO_msg_size;
  IO_logic_ptr_t        IO_logic_ptr;
  //... other members as required by Equipment_setup.h ...
  //... members that vary based on the controller's SDK ...
};

Спасибо за быстрый ответ. Если я правильно понимаю, то я бы оставил свои предварительные объявления (?? это правильный термин, я думаю, что нет) такими же в Equipment_setup.h. Что-то, что я думаю, имеет большое значение, так это тот факт (о котором я забыл упомянуть), что в Controller_setup.h есть структуры и функции, которые также используют эти типы данных typedef.

MidnightRover 08.04.2019 03:15

Но вы помогли, и я думаю, что начинаю видеть разницу между тем, как я думаю, что вещи работают, и тем, как они работают на самом деле. Я примерно понял, что typedef — это способ создания аббревиатур в том смысле, что он был почти как макрос, избавляющий меня от необходимости вводить enum или struct в начале, но на самом деле он ничего не определял сам по себе. Но, как следует из названия, оно используется для определения символа.

MidnightRover 08.04.2019 03:16

В моем исходном примере вы можете думать об этом так, как будто в Equipment_setup.h я определяю объявление, а в Controller_setup.h я определяю определение. Таким образом, структура IO_link_t имеет одно объявление и одно определение, что нормально, но IO_link_t определяется в двух местах, что не так.

MidnightRover 08.04.2019 03:16

Так что, если я все правильно понимаю, одним из способов было бы просто избежать typedef и просто заменить все на структура IO_link_t??

MidnightRover 08.04.2019 03:16

@MidnightRover Вы можете сохранить typedef, просто сделайте это только в одном месте.

dbush 08.04.2019 03:18

Обратите внимание, что C11 (и C18) позволяют вам определять typedef в два раза дольше, если он идентичен для каждой связи. Я не использовал эту функцию (сознательно) и не собираюсь этого делать. Однако он существует — см. C11 §6.7 Декларации ¶3: имя typedef может быть переопределено для обозначения того же типа, что и в настоящее время, при условии, что этот тип не является изменяемым типом.

Jonathan Leffler 08.04.2019 08:00

Другие вопросы по теме