#c #typedef #forward-declaration
#c #typedef #прямое объявление
Вопрос:
Итак .. У меня происходит что-то вроде курицы и яйца.
Я получил Controller_setup.h и Equipment_setup.h, которые используют определения типа, определенные в другом. Я мог бы много написать здесь об обосновании того, почему это так, но воздержусь от этого, если кто-то действительно не захочет знать (хотя в основном это была попытка заставить код в Equipment_setup.c / h работать с разными системами контроллеров, просто имея другой Controller_setup.h).
На предыдущем контроллере и компиляторе (контроллер использовал процессор ARM, а мы использовали компилятор IAR и IDE) мы разработали код, в котором я смог переадресовать объявление / переопределение определений типа, и это сработало бы. Это дало бы нам много предупреждений, но это скомпилировалось бы и сработало.
Теперь, когда мы фактически пытаемся перенести на другой контроллер, используя другую 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 считывается.
Сообщение об ошибке:
- ошибка: [12993] переопределение typedef ‘IO_link_t’
- ошибка: [13256] предыдущее объявление ‘IO_link_t’ было здесь
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;
Ответ №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 ...
};
Комментарии:
1. спасибо за быстрый ответ. Если я правильно понимаю, то я бы оставил свои прямые объявления (?? это правильный термин, я думаю, что нет) одинаковыми в Equipment_setup.h . Что, на мой взгляд, имеет большое значение, так это тот факт (о котором я забыл упомянуть), что в Controller_setup.h есть структуры и функции, которые также используют эти типы данных typedef.
2. Но вы помогли, и я думаю, что начинаю видеть разницу между тем, как я думаю, что все работает, и тем, как они работают на самом деле. Я вроде как понял, что typedef — это способ создания абревиатур, поскольку это было почти как макрос, где это избавляло меня от необходимости вводить enum или struct в начале, но само по себе это ничего не определяло. Но, как следует из названия, оно используется для определения символа.
3. В моем исходном примере вы можете думать об этом как о Equipment_setup . h Я определяю объявление, где, как в Controller_setup. h Я определяю определение. Итак, структура IO_link_t имеет одно объявление и одно определение, что нормально, но IO_link_t определяется в двух местах, чего нет.
4. Итак, если я все это правильно понимаю, одним из способов обойти это было бы просто избежать typedef и просто заменить все на struct IO_link_t ??
5. @MidnightRover Вы можете сохранить
typedef
, просто сделайте это только в одном месте.