MidnightRover
MidnightRover

Reputation: 197

C: Forward declaring a typedef that will be defined later for being used in declaring a function now

So.. I got a bit of a chicken and egg thing going on.

I got Controller_setup.h and Equipment_setup.h which use typedefs defined in the other. I could write a whole lot here about justifying why this is but will refrain from doing so unless someone really really wants to know (though basically it was an attempt to have the code in Equipment_setup.c/h work with different controller systems simply by having a different Controller_setup.h).

On the previous controller and compiler (controller used an ARM processor and we were using the IAR compiler and IDE) we developed the code on I was able to forward declare/redefine the typedefs and it would work. It would give us lots of warnings but it would compile and work.

Now that we are actually trying to port over to another controller using another IDE and compiler (controller uses a TriCore processor and we are using the Code::blocks IDE with GNU GCC compiler for TriCore V3.4.6) it's now raising errors and won't let the code compile.

I am very new to this, but from what I understood I should be able to at any time put a declaration saying that this datatype is defined somewhere so the compiler shouldn't worry when I reference that datatype in my function declarations.

Since it worked on one compiler (admittedly with warnings) I am hoping that there is some way to make it work now. I don't suppose it's something as simple as using a different syntax is it? Is it possible to declare a typedef vs redefining it?

Actually I just googled that exact question and by following that trail I seem to now understand that what I want to do is allowed under C11, but not previous C standards. And as far as I can tell the Tricore compiler doesn't support C11 so this is likely why it used to work but not now.

But if someone could help verify this understanding that would be appreciated.

I really don't want to have to find a work around as I fear it may mean a fairly substantial rework of how the program is structured. It would likely be better in the long run, but now is not a good time to have to do it.

Below is a simplified version of what had worked but not now. I have left out the parts where Controller_setup.h is referencing Equipment_setup.h. When the project is built Equipment_setup.h is read first so I then get the error when the redefinition in Controller_setup.h is read.

The error message is:

  • 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;

Upvotes: 1

Views: 520

Answers (1)

dbush
dbush

Reputation: 223739

When you do this:

typedef struct IO_link_t IO_link_t;

The typedef defines a type. You're also declaring struct IO_link_t. When you then do this:

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;

You define struct IO_link_t which was previously not defined but you also redefine the type IO_link_t. That's where the error comes from. The same goes for the enum.

You can fix this by removing the typedef at the point the struct and enum are defined.

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 ...
};

Upvotes: 2

Related Questions