31

When should one of the following statements be used over the other?

typedef struct Foo {
    int a;
} Bar;

and

typedef struct {
    int a;
} Bar;

and use it like

Bar bar1 = { 5 };

I understand the second one is an anonymous struct but not sure when should one be used over the other.

4
  • 5
    When you create a linked list, for example, you need to use the name of the struct inside the struct - in which case you have to use the first example. in other cases I don't think there is an advantage to the first over the second Commented Feb 18, 2019 at 18:00
  • Related: stackoverflow.com/q/54753213/6699433 Commented Feb 18, 2019 at 18:35
  • This is an almost exact duplicate of stackoverflow.com/questions/1110944/… but since both the question and the answers here are better I don't want to have this one closed. What's the appropriate action here? Flagging the other question (which is 10 years old!) as a duplicate of this one? Commented Feb 19, 2019 at 11:43
  • @FabioTurati There is nothing that says that the newer should be a duplicate of the older. Quality of questions and answers are far more important, so if you think the way you do, it is perfectly ok to flag the older one as a dup of this. Commented Jul 22, 2019 at 22:38

6 Answers 6

30

They are pretty much equivalent. Actually, you can AND SHOULD use the same name on both places. Use the same name unless you can come up with a good reason not to.

One situation where you want the non-anonymous is when you want pointers to an object of the same type, like in a linked list.

typedef struct Node {
    struct Node* next;
    int data;
} Node;

One alternative:

typedef struct Node Node;

struct Node {
    Node * next;
    int data;
};

According to Linus Torvalds, you should avoid typedefing structs unless you want to hide it. From the Linux kernel coding style guide:

Please don’t use things like vps_t. It’s a mistake to use typedef for structures and pointers. When you see a vps_t a; in the source, what does it mean? In contrast, if it says struct virtual_container *a; you can actually tell what a is.

Lots of people think that typedefs help readability. Not so. They are useful only for:

a) totally opaque objects (where the typedef is actively used to hide what the object is).

...

According to that, you should never use anonymous structs, and the typedefs are strictly for interfaces. So it should look like this:

typedef struct Node {
    struct Node* next;
    int data;
} Node;

But if you are really creating an interface, you should in general separate it into a header file and a source file. In this case, put the typedef in the header file and do NOT use the typedef:ed type at all in the source file.

.c

struct Node {
    struct Node* next;
    int data;
} Node;

void insert(struct Node* head, int data) 
{
// Code
}    

.h

typedef struct Node Node;

void insert(Node* head, int data);

Taking all of the above into consideration, the only valid situation to use an anonymous struct is if you declare an object at the same time like this:

struct {
    int data;
    float more_data;
} myObject; 
Sign up to request clarification or add additional context in comments.

2 Comments

Well one difference I just found out is that you can't define static members inside anonymous/unnamed structures; that's because then you cannot access it properly. For example, if you go struct {static int a; int b;}; then you cannot set a via i.e. int MyStructName::a = 0;, because myStructName is not defined.
@MicheleIafrancesco This is not about C++
7

One time where the former is required is if you're making a linked list:

typedef struct list {
    int data;
    struct list *next;
} list;

The typedef list is not visible inside of the struct definition, so you need to use the actual struct name to create a pointer to it.

If you don't have such a structure, you can use either one.

What you shouldn't do however is use a tag name that starts with an underscore, i.e.:

typedef struct _list {
    int data;
    struct list *next;
} list;

Because names starting with a underscore are reserved by the implementation.

1 Comment

It's more complcated, but never starting with an underscore nor using consecutive underscores is a good rule of thumb.
4

The term anonymous struct is already used for something else: in nested structs (or unions) that don't have a name at all and whose fields are referred to as if they were entries in the parent.

The actual question about when to use one or the other is that you have to use the first form if you want to add a pointer to its own type inside it like so:

typedef struct Foo { struct Foo* Child; ... } Foo;

However, what I would prefer is to do that with a typedef like so:

typedef struct Foo Foo;
struct Foo {Foo* Child;};

Comments

2

A lot of other people are focusing on the self referential aspect of this, but another reason to avoid doing this is that due to the lack of namespaces in C. In some circles it is standard practice to not typedef structs to avoid struct qualifier and instead refer to structs with the full specifier (eg void foo(struct Foo* foo_ptr)). So if you wanted to maintain such a style, you wouldn't have the option to abuse anonymous structs, so this:

typedef struct {
  int a;
} Bar;

Bar bar1 = {5};

should always instead be

struct Bar{
  int a;
};

struct Bar bar1 = {5};

otherwise you couldn't even compile bar1's instantiation with out typedefing away the struct qualifier

7 Comments

What's the benefit? The vast majority of custom types are structs, not enums or unions. It's pretty clear that you're talking about a struct, without explicitly stating it.
@Alexander it isn't about being clear that something is a struct, its about maximizing use of the single namespace C gives you. A typedefd struct name can conflict with enums, unions, functions and structs, but if you don't typedef out the struct qualifier, structs can only conflict with other structs, greatly reducing the potential for namespace conflicts.
If your struct names conflict with functions, unions or enums, then your names suck. Structs should be nouns, functions should be verbs and verb phrases, thus they should never overlap. Enum names almost always imply they're enums, with words like FooKind, FooTypes, FooIDs, etc., and unions are pretty rare. You should never really use unions directly, anyway, so their names are usually some kind of _ prefixed private API. A union doesn't store its "active case", so you almost always have to use it as part of a struct that also stores an enum tag.
@Alexander There are quite a lot of nouns and verbs that are spelled the same way. Like attack, echo, catch, battle, work just to name a few.
@klutt Fair enough, but I still don't think that's justification for this. C only gives you 4 namespaces (that I know of). The global one, and the ones for structs, unions and enum. If your name is conflict prone, and your only workaround is to move it from the global namespace to the struct namespace, then that's pretty crappy.
|
1

When creating an opaque data type which is when the header only contains a forward declaration of the struct and the actual definition of it's members is in the source file. Since you cannot forward declare a typedef you'll have to give a struct a name. Example:

Foo.h

typedef struct Foo_ Foo;

Foo.c

struct Foo_ {
    int a;
};

Also when you have a recursive data structure such as linked list which everyone else has mentioned.

1 Comment

Why the underscore on Foo_?
0

Prefer tagged structs, possibly type-aliased (==typedef'd) to the same tag (unless you have a good reason to use a different tag)

With those you can have:

1. links to the same type
2. forward struct declarations (opaque structs => fewer/leaner includes => faster compilations times)

1.

To have links to the same type you need a tag:

or like so:

2. To forward-declare, you also need a tag.

struct node_tp; /*can also typedef it at the same time: typedef struct node_tp node_tp*/

With these you can keep the struct opaque (never expose the layout in a public interfaces) or you can use them in a translation units that just pass around struct node_tp pointers without allocating or accessing the contents.

Opaque struct API are good for encapsulations. And even if the API doesn't make the struct actually opaque, using forward-declared structs can lead to greater translation unit decoupling => faster build times.

You can't do these two things with (typedefed or not) anonymous structs, so that's why I prefer tagging (and then I don't think about whether I need opaque types/same-type-link members).

You can typedef to avoid having to mention the struct keywords at use points. Linus Torvalds has expressed concerns against that (https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs) but you can just as well use a naming convention to encode the struct-ness into the tag, dispelling his readability concern.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.