1

I have the following code in my C header file:

typedef struct mb32_packet_t {
  uint8_t compid;
  uint8_t servid;
  uint8_t payload[248];
  uint8_t checksum;
} __attribute__((packed)) mb32_packet_s;

Doing the following works:

struct mb32_packet_t packet;

When using this:

mb32_packet_t packet;

I get:

Type 'mb32_packet_t' could not be resolved
Unknown type name 'mb32_packet_t'; use 'struct' keyword to refer to the type

Isn't typedef struct intended for exactly this purpose, i.e. to be able to omit the struct keyword when defining variables of this type?

salocinx
  • 3,715
  • 8
  • 61
  • 110

3 Answers3

1

Your alias defined by typedef is called mb32_packet_s. So you need to use it as

mb32_packet_s packet;

or

struct mb32_packet_t packet;

You can also rename the alias to mb32_packet_t:

typedef struct mb32_packet_t {
  uint8_t compid;
  uint8_t servid;
  uint8_t payload[248];
  uint8_t checksum;
} __attribute__((packed)) mb32_packet_t;

Then you can do both (original name without alias)

struct mb32_packet_t packet;

and (with alias)

mb32_packet_t packet;

This way, the names of both alias and the struct are identical, but technically, struct mb32_packet_t and mb32_packet_t are two different things that however refer to the same type.

Erlkoenig
  • 2,664
  • 1
  • 9
  • 18
  • Thanks explaining, I will use it as you describe! But for understanding my original `struct` definition: `mb32_packet_s` is actually an object, i.e. allocated memory, correct? And when later writing `mb32_packet_s packet;` this will not allocate new memory; i.e. `packet` is only kind of a reference to `mb32_packet_s` ? – salocinx Mar 02 '20 at 11:48
  • No, only `packet` is an object, i.e. reserves memory. `mb32_packet_s` is just an alias for `struct mb32_packet_t`, i.e. both are types. – Erlkoenig Mar 02 '20 at 12:15
  • Now I guess I understand. And if I would define/initialize `mb32_packet_s={...}` at the end of the struct, `mb32_packet_s` would indeed be an object residing in memory? – salocinx Mar 02 '20 at 12:17
  • You can't do that together with `typedef`. You can do `struct X { ...} instance = {...};` which will create an instance (object) of the struct type, but won't define an alias. If you want both an instance and an alias, you do `typedef struct X {...} X; X instance = {...};` or `struct X {...}; typedef struct X X; X instance={...};` or `struct X {...} instance = {...}; typedef struct X X;` – Erlkoenig Mar 02 '20 at 12:21
  • Now I got it :) ! Thanks for your patience! – salocinx Mar 02 '20 at 12:24
1

The declaration typedef struct mb32_packet_t ... mb32_packet_s; makes mb32_packet_t a tag that only works after the keyword struct and makes mb32_packet_s a type name that works on its own. To make mb32_packet_t a type name, swap them in the declaration or use mb32_packet_t in both places.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • Thanks! So `typedef` does nothing in this case? I mean without `typedef` I can use it the same way, correct? – salocinx Mar 02 '20 at 11:52
  • @salocinx: `typedef` says the identifier declared is a type name rather than an object or function. `typedef struct foo bar` makes `bar` a name for `struct foo`. `struct foo bar` makes an object named `bar` of type `struct foo`. – Eric Postpischil Mar 02 '20 at 11:56
  • Just to clarify; at my original `struct` definition `mb32_packet_s;` is already an object of type `mb32_packet_t`, i.e. memory allocated. Later when I do `mb32_packet_s packet;` it does allocate a new object in memory with name `packet` ? Sorry for being that persistent, I want to understand. – salocinx Mar 02 '20 at 12:11
  • ... or would only be memory allocated when I initialize/define the variable `mb32_packet_s` with `={...}` at the end of the `struct` definition? – salocinx Mar 02 '20 at 12:15
  • @salocinx: The declaration shown first in your question, `typedef struct mb32_packet_t { … } __attribute((packed)) mb32_packet_s;`, does not define any object and does not cause memory to be reserved. It merely defines a name for a type. If you have further questions about the effects of various declarations, you should enter a new question showing complete samples. Attempting to describe them partially in comments results in lack of clarity. – Eric Postpischil Mar 02 '20 at 12:17
  • Ok I get closer to understand. But if I would have defined `mb32_packet_s={...}` at the end of the `struct` definition, it would indeed be allocated in memory instead of being a name for the type `mb32_packet_t`? – salocinx Mar 02 '20 at 12:20
  • @salocinx: No. The `={…}` supplies an initial value for an object. A `typedef` does not declare an object. You would get an error message from the compiler. If you have further questions about the effects of various declarations, enter a new question showing **complete samples** — complete code that can be compiled. – Eric Postpischil Mar 02 '20 at 12:23
  • Thanks a lot for your patience! I think I got my head around what I initially didn't understand. So you helped me a lot! – salocinx Mar 02 '20 at 12:26
1

In your typedef struct... code, the mb32_packet_t is a structure tag, not the name of the defined type, which is mb32_packet_s. You can use the tag in a variable declaration, but only if you also include the struct keyword.

To declare a variable of the type without the struct keyword, you need to use the type's actual name, as follows:

mb32_packet_s packet; // Note the "_s" rather than "_t" and the end.
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83