[c++] Difference between 'struct' and 'typedef struct' in C++?

In C++, is there any difference between:

struct Foo { ... };

and:

typedef struct { ... } Foo;

This question is related to c++ struct typedef

The answer is


One more important difference: typedefs cannot be forward declared. So for the typedef option you must #include the file containing the typedef, meaning everything that #includes your .h also includes that file whether it directly needs it or not, and so on. It can definitely impact your build times on larger projects.

Without the typedef, in some cases you can just add a forward declaration of struct Foo; at the top of your .h file, and only #include the struct definition in your .cpp file.


In this DDJ article, Dan Saks explains one small area where bugs can creep through if you do not typedef your structs (and classes!):

If you want, you can imagine that C++ generates a typedef for every tag name, such as

typedef class string string;

Unfortunately, this is not entirely accurate. I wish it were that simple, but it's not. C++ can't generate such typedefs for structs, unions, or enums without introducing incompatibilities with C.

For example, suppose a C program declares both a function and a struct named status:

int status(); struct status;

Again, this may be bad practice, but it is C. In this program, status (by itself) refers to the function; struct status refers to the type.

If C++ did automatically generate typedefs for tags, then when you compiled this program as C++, the compiler would generate:

typedef struct status status;

Unfortunately, this type name would conflict with the function name, and the program would not compile. That's why C++ can't simply generate a typedef for each tag.

In C++, tags act just like typedef names, except that a program can declare an object, function, or enumerator with the same name and the same scope as a tag. In that case, the object, function, or enumerator name hides the tag name. The program can refer to the tag name only by using the keyword class, struct, union, or enum (as appropriate) in front of the tag name. A type name consisting of one of these keywords followed by a tag is an elaborated-type-specifier. For instance, struct status and enum month are elaborated-type-specifiers.

Thus, a C program that contains both:

int status(); struct status;

behaves the same when compiled as C++. The name status alone refers to the function. The program can refer to the type only by using the elaborated-type-specifier struct status.

So how does this allow bugs to creep into programs? Consider the program in Listing 1. This program defines a class foo with a default constructor, and a conversion operator that converts a foo object to char const *. The expression

p = foo();

in main should construct a foo object and apply the conversion operator. The subsequent output statement

cout << p << '\n';

should display class foo, but it doesn't. It displays function foo.

This surprising result occurs because the program includes header lib.h shown in Listing 2. This header defines a function also named foo. The function name foo hides the class name foo, so the reference to foo in main refers to the function, not the class. main can refer to the class only by using an elaborated-type-specifier, as in

p = class foo();

The way to avoid such confusion throughout the program is to add the following typedef for the class name foo:

typedef class foo foo;

immediately before or after the class definition. This typedef causes a conflict between the type name foo and the function name foo (from the library) that will trigger a compile-time error.

I know of no one who actually writes these typedefs as a matter of course. It requires a lot of discipline. Since the incidence of errors such as the one in Listing 1 is probably pretty small, you many never run afoul of this problem. But if an error in your software might cause bodily injury, then you should write the typedefs no matter how unlikely the error.

I can't imagine why anyone would ever want to hide a class name with a function or object name in the same scope as the class. The hiding rules in C were a mistake, and they should not have been extended to classes in C++. Indeed, you can correct the mistake, but it requires extra programming discipline and effort that should not be necessary.


There is no difference in C++, but I believe in C it would allow you to declare instances of the struct Foo without explicitly doing:

struct Foo bar;

You can't use forward declaration with the typedef struct.

The struct itself is an anonymous type, so you don't have an actual name to forward declare.

typedef struct{
    int one;
    int two;
}myStruct;

A forward declaration like this wont work:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types

Struct is to create a data type. The typedef is to set a nickname for a data type.


There is a difference, but subtle. Look at it this way: struct Foo introduces a new type. The second one creates an alias called Foo (and not a new type) for an unnamed struct type.

7.1.3 The typedef specifier

1 [...]

A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in the way described in Clause 8. A typedef-name is thus a synonym for another type. A typedef-name does not introduce a new type the way a class declaration (9.1) or enum declaration does.

8 If the typedef declaration defines an unnamed class (or enum), the first typedef-name declared by the declaration to be that class type (or enum type) is used to denote the class type (or enum type) for linkage purposes only (3.5). [ Example:

typedef struct { } *ps, S; // S is the class name for linkage purposes

So, a typedef always is used as an placeholder/synonym for another type.


An important difference between a 'typedef struct' and a 'struct' in C++ is that inline member initialisation in 'typedef structs' will not work.

// the 'x' in this struct will NOT be initialised to zero
typedef struct { int x = 0; } Foo;

// the 'x' in this struct WILL be initialised to zero
struct Foo { int x = 0; };

Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to struct

How to search for an element in a golang slice "error: assignment to expression with array type error" when I assign a struct field (C) How to set default values in Go structs How to check for an empty struct? error: expected primary-expression before ')' token (C) Init array of structs in Go How to print struct variables in console? Why Choose Struct Over Class? How to return a struct from a function in C++? Initializing array of structures

Examples related to typedef

How do I use typedef and typedef enum in C? Overloading operators in typedef structs (c++) What is the difference between 'typedef' and 'using' in C++11? typedef fixed length array Typedef function pointer? C++ template typedef dereferencing pointer to incomplete type uint8_t vs unsigned char typedef struct vs struct definitions Understanding typedefs for function pointers in C