1015

I'm a beginner in C programming, but I was wondering what's the difference between using typedef when defining a structure versus not using typedef. It seems to me like there's really no difference, they accomplish the same goal.

struct myStruct{
    int one;
    int two;
};

vs.

typedef struct{
    int one;
    int two;
}myStruct;
roschach
  • 8,390
  • 14
  • 74
  • 124
user69514
  • 26,935
  • 59
  • 154
  • 188

12 Answers12

1300

The common idiom is using both:

typedef struct S { 
    int x; 
} S;

They are different definitions. To make the discussion clearer I will split the sentence:

struct S { 
    int x; 
};

typedef struct S S;

In the first line you are defining the identifier S within the struct name space (not in the C++ sense). You can use it and define variables or function arguments of the newly defined type by defining the type of the argument as struct S:

void f( struct S argument ); // struct is required here

The second line adds a type alias S in the global name space and thus allows you to just write:

void f( S argument ); // struct keyword no longer needed

Note that since both identifier name spaces are different, defining S both in the structs and global spaces is not an error, as it is not redefining the same identifier, but rather creating a different identifier in a different place.

To make the difference clearer:

typedef struct S { 
    int x; 
} T;

void S() { } // correct

//void T() {} // error: symbol T already defined as an alias to 'struct S'

You can define a function with the same name of the struct as the identifiers are kept in different spaces, but you cannot define a function with the same name as a typedef as those identifiers collide.

In C++, it is slightly different as the rules to locate a symbol have changed subtly. C++ still keeps the two different identifier spaces, but unlike in C, when you only define the symbol within the class identifier space, you are not required to provide the struct/class keyword:

 // C++
struct S { 
    int x; 
}; // S defined as a class

void f( S a ); // correct: struct is optional

What changes are the search rules, not where the identifiers are defined. The compiler will search the global identifier table and after S has not been found it will search for S within the class identifiers.

The code presented before behaves in the same way:

typedef struct S { 
    int x; 
} T;

void S() {} // correct [*]

//void T() {} // error: symbol T already defined as an alias to 'struct S'

After the definition of the S function in the second line, the struct S cannot be resolved automatically by the compiler, and to create an object or define an argument of that type you must fall back to including the struct keyword:

// previous code here...
int main() {
    S(); 
    struct S s;
}
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • 12
    @AlexanderVarwijk: You want to `typedef` to avoid the need to qualify with `struct` or `enum`. If the naming conventions you use allow for a function and a type by the same name, the best you can do is review how you name the elements of your program. – David Rodríguez - dribeas Jul 20 '13 at 18:45
  • 1
    My naming conventions should make sure that doesn't happen, better safe than sorry though : ) – Alexander Varwijk Jul 21 '13 at 12:56
  • 2
    Are there any downsides on giving the type the same name as the `struct` or `enum`? E.g. if you write a lib and want concise type names and don't want to think of different names for the underlying structs and enums. Some structs might not be defined publicly (they are only accessed through pointers) and only the typedefed names are (will be) documented. – panzi Oct 21 '13 at 23:33
  • 5
    @panzi: I cannot think of any downside, on the contrary, it will probably make more sense for other users if the type and the typename have the same name. – David Rodríguez - dribeas Oct 22 '13 at 04:35
  • Basically, use differing identifier names to avoid confusion. :D – trusktr Jul 09 '14 at 03:19
  • 19
    This answer explains how the compiler works, and using `typedef` is a good idea— however, it doesn't explain why the `struct` should be given a name when using the `typedef`-only form of declaration (2nd example in the question).  This is also where I've been at a loss for ~15 years of off-and-on C/C++ programming, and the most important piece of information beyond what I've been taught: _“just always use `typedef`; not using it is a pain in the ass”_. – Slipp D. Thompson Sep 13 '15 at 18:50
  • 1
    Should enums also be given the name both ways, just like structs? – Panzercrisis Apr 01 '16 at 21:43
  • 16
    @SlippD.Thompson The reason to give the `struct` a name in the tag namespace is so that it could possibly be forward-declared. `typedef`-only creates an alias to an anonymous `struct`, and this cannot be forward-declared. http://stackoverflow.com/a/612350/2757035 – underscore_d Apr 09 '16 at 16:14
  • 1
    @underscore_d Exactly. I've downvoted this answer and upvoted RSamuelKlatchko's for this reason; this answer explains a bunch of the internals without actually providing pactical; RSamuel's concisely answers what a C++ programmer needs to know to write good reliable code. – Slipp D. Thompson Apr 09 '16 at 16:46
  • @SlippD.Thompson: The question happens to be C, in C++ you would not provide the typedef... but yes, ability to forward declare is not explicitly mentioned in the answer, it is implicit but on separating the alias from the actual type, but it could be more explicit. – David Rodríguez - dribeas Apr 10 '16 at 20:39
  • 1
    @DavidRodríguez-dribeas What's also not explicitly mentioned in your answer is anything that approaches what is _accomplished_ (human programmer-wise) by using `typedef`. Instead you talk about the compiler's symbol resolution, and potential name-conflict pitfalls that lazy programmers could fall into (those who don't strive to give every construct a distinct meaningful name). I mean it's an interesting answer and good-to-know for hard-core C++ programmers, so don't get me wrong, it's not a bad answer. It's just not _the answer_ the OP was after (IMHO). It's internals when the OP wanted usage. – Slipp D. Thompson Apr 10 '16 at 20:48
  • 1
    @DavidRodríguez-dribeas am I right to think it was a totally goofy for C to make this separate `struct` namespace and require the `struct` keyword everywhere unless you use `typedef struct` statements, or was there some kind of good reason for it I should know about? Because it seems to me people mostly just use the `typedef struct` statements to defeat the need purpose of the separate namespacing. – Andy Nov 12 '17 at 00:53
  • 1
    @Andy: I was not there and I don't really know the design decisions. One thing that comes to mind is that, except for `typedef` names, the general identifier space contains things that would appear as symbols in the binary. – David Rodríguez - dribeas Nov 15 '17 at 22:07
  • 1
    @SlippD.Thompson: "It seems to me like there's really no difference, they accomplish the same." The answer tries to address the fact that there is a difference and where the difference lies, including scenarios that would make that visible as when there are no name collisions there is no perceivable difference. – David Rodríguez - dribeas Nov 15 '17 at 22:11
  • Is the following syntax valid `typedef struct{ int x; } T;` and then `T varName;`? – roschach Dec 04 '18 at 14:13
  • 1
    A better answer can be found at [here](https://stackoverflow.com/a/612350/3484477) – Meysam Sadeghi Aug 29 '19 at 09:34
  • 1
    Why not move the `typedef struct S S;` **before** the `struct S { ... };` definition? It has 2 advantages: `S` can be used as a type for pointers inside the definition of `struct S`, for example for list links, and the actual definition is not actually required if you only manipulate opaque pointers, in which case the `typedef` could be moved to another header file. – chqrlie Feb 09 '20 at 16:54
  • @SlippD.Thompson What do you mean by "*anything that approaches what is accomplished (human programmer-wise) by using `typedef`.*" exactly? – RobertS supports Monica Cellio Feb 09 '20 at 17:22
  • 1
    @RobertSsupportsMonicaCellio I came here looking for an answer about what's advantageous for software developers to use `typedef` for software development— the technical and design field that's concerned with both how things work, and how to organize and structure things so they make sense to other humans, and are maintainable over time and across systems and frameworks. What I received were answers like this one that were only concerned with technical computer science— how code is turned into assembly, and how certain software design features produce the same assembly. – Slipp D. Thompson Feb 09 '20 at 17:35
  • @SlippD.Thompson I see, that your first ping to `@DavidRodriguez` is almost 4 1/2 years ago, Sept, 2015. Can I ask you if you found answers to these (your) questions in the meantime anywhere else? I would be interested in those answers, too. – RobertS supports Monica Cellio Feb 09 '20 at 17:44
  • @RobertSsupportsMonicaCellio I have no idea. It was 4 1/2 years ago. I don't do much C++ anymore. – Slipp D. Thompson Feb 09 '20 at 17:44
213

struct and typedef are two very different things.

The struct keyword is used to define, or to refer to, a structure type. For example, this:

struct foo {
    int n;
};

creates a new type called struct foo. The name foo is a tag; it's meaningful only when it's immediately preceded by the struct keyword, because tags and other identifiers are in distinct name spaces. (This is similar to, but much more restricted than, the C++ concept of namespaces.)

A typedef, in spite of the name, does not define a new type; it merely creates a new name for an existing type. For example, given:

typedef int my_int;

my_int is a new name for int; my_int and int are exactly the same type. Similarly, given the struct definition above, you can write:

typedef struct foo foo;

The type already has a name, struct foo. The typedef declaration gives the same type a new name, foo.

The syntax allows you to combine a struct and typedef into a single declaration:

typedef struct bar {
    int n;
} bar;

This is a common idiom. Now you can refer to this structure type either as struct bar or just as bar.

Note that the typedef name doesn't become visible until the end of the declaration. If the structure contains a pointer to itself, you have use the struct version to refer to it:

typedef struct node {
    int data;
    struct node *next; /* can't use just "node *next" here */
} node;

Some programmers will use distinct identifiers for the struct tag and for the typedef name. In my opinion, there's no good reason for that; using the same name is perfectly legal and makes it clearer that they're the same type. If you must use different identifiers, at least use a consistent convention:

typedef struct node_s {
    /* ... */
} node;

(Personally, I prefer to omit the typedef and refer to the type as struct bar. The typedef saves a little typing, but it hides the fact that it's a structure type. If you want the type to be opaque, this can be a good thing. If client code is going to be referring to the member n by name, then it's not opaque; it's visibly a structure, and in my opinion it makes sense to refer to it as a structure. But plenty of smart programmers disagree with me on this point. Be prepared to read and understand code written either way.)

(C++ has different rules. Given a declaration of struct blah, you can refer to the type as just blah, even without a typedef. Using a typedef might make your C code a little more C++-like -- if you think that's a good thing.)

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • 7
    This answer helped me better understand why both C89 libraries and the Linux kernel are more likely to use `struct mystruct_t {}` rather than `typedef struct {} mystruct_t`. – Josh Sanford Jul 25 '16 at 13:05
  • 1
    @KeithThompson Good answer +1. I personally would like to know why or why not to omit the structure tag when using typedef, like the OP did it in his question: `typedef struct{ int one; int two; }myStruct;`. Someones say it is because of forward declaration, but in this [comment](https://stackoverflow.com/questions/1675351/typedef-struct-vs-struct-definitions/1675446?noredirect=1#comment45197878_1675527) another user said this is also possible with typedefs. Is there a reason to not omit it? – RobertS supports Monica Cellio Feb 09 '20 at 19:09
  • 1
    One thing more: Didn´t you meant "*Using a typedef might make your C++ code a little more C-like*" instead of "*Using a typedef might make your C code a little more C++-like*"? – RobertS supports Monica Cellio Feb 09 '20 at 19:11
  • 3
    @RobertSsupportsMonicaCellio You can't do a forward declaration without a tag. The example in the linked comment used a typedef *and* a tag. No, I meant using a typedef can make C code more C++-like. In C++, structs (and classes, and unions, and enums) are referred to using a name that's a single identifier. Referring to a type as `struct foo` is more C-like. – Keith Thompson Feb 09 '20 at 22:19
97

Another difference not pointed out is that giving the struct a name (i.e. struct myStruct) also enables you to provide forward declarations of the struct. So in some other file, you could write:

struct myStruct;
void doit(struct myStruct *ptr);

without having to have access to the definition. What I recommend is you combine your two examples:

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

This gives you the convenience of the more concise typedef name but still allows you to use the full struct name if you need.

R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
  • 1
    There are ways to do forward declarations with typedef: `typedef struct myStruct myStruct;`; and then (later): `struct myStruct { ... };`. You can use it as *either* `struct myStruct` *or* just `myStruct` after that `typedef` (but the type is incomplete until that definition). – Tim Čas Feb 10 '15 at 14:20
  • It's also worth mentioning that C++, despite (conceptually) auto-typedef'ing tags and putting both `struct SomeThing` and `Something` in a single 'symbolspace', does make an explicit allowance for a manual `typedef SomeThing` to redefine to `struct SomeThing`... where you might otherwise assume this would generate an error about clashing names. Source: http://stackoverflow.com/a/22386307/2757035 I guess this was done for (slightly futile!) backwards compatibility reasons. – underscore_d Apr 09 '16 at 16:52
  • @underscore_d: At the time, people recognized the value in having code which could work equally well as C and C++, and wanted to avoid creating needless barriers to compatibility. Sadly, such thinking is no longer fashionable. – supercat Apr 15 '17 at 20:53
71

In C (not C++), you have to declare struct variables like:

struct myStruct myVariable;

In order to be able to use myStruct myVariable; instead, you can typedef the struct:

typedef struct myStruct someStruct;
someStruct myVariable;

You can combine struct definition and typedefs it in a single statement which declares an anonymous struct and typedefs it.

typedef struct { ... } myStruct;
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 1
    The last block of code is not equivalent to the previous code. In the last line you are defining a type alias 'myStruct' into an unnamed struct. There are (very) subtle difference among the two versions. – David Rodríguez - dribeas Nov 04 '09 at 17:52
  • 5
    dribeas: I covered this subtle difference in the sentence "...a single statement which declares **an anonymous struct** and..." – Mehrdad Afshari Nov 04 '09 at 18:10
  • @DavidRodríguez-dribeas Care to elaborate on the subtle differences? – Anthony Mar 21 '13 at 00:12
  • 3
    @anthony-arnold: Uhm... I think I already mentioned. In one case there is a type with a name and also an alias, in the other you only have an alias. Where does it matter? Seldomly, but if you have an annonymous type you cannot do `struct T x;` to declare a variable, or reuse the name for a different type of symbol: `typedef struct {} f; void f(); struct f x;` fails in the last two statements. Of course, having code like that is not recommended (a type and a function with the same name?) – David Rodríguez - dribeas Mar 21 '13 at 02:19
  • Thank you for saying the magic word: **annonymous struct**. It was only standardized in C11. – Ciro Santilli OurBigBook.com Sep 15 '14 at 18:44
  • 2
    The accepted answer didn't do a good job contrasting "struct" and "typedef struct", this answer made it clear for me that the "typedef struct" technique is used so C can emulate C++ in order to omit "struct" when using the structure like a data type when passing it. – Ultimater Apr 07 '16 at 04:46
48

If you use struct without typedef, you'll always have to write

struct mystruct myvar;

It's illegal to write

mystruct myvar;

If you use the typedef you don't need the struct prefix anymore.

nbro
  • 15,395
  • 32
  • 113
  • 196
RED SOFT ADAIR
  • 12,032
  • 10
  • 54
  • 92
  • 9
    My answer is not up to date anymore. Current compilers treat "typedef struct" and "struct" the same. Both can be referenced without the "struct" prefix.. I.e. VC2013 behaves that way. – RED SOFT ADAIR Mar 29 '18 at 13:23
  • 1
    I appreciate you short answer as well as the other accepted. For the sake of order what do you mean for "Current compilers"? What type of C version do you refer? For example, I tested the behavior during a cross compile with ARM compiler (C99). In my case "typedef struct" and "struct" are not treat ad the same. – bitfox Mar 15 '19 at 11:19
  • VC 2017 and later (possibly also earlier) versions do not require to write struct... when instantatin a object. More i can not tell. – RED SOFT ADAIR Mar 16 '19 at 12:20
  • 5
    @REDSOFTADAIR *"Current compilers treat "`typedef struct`" and "`struct`" the same. Both can be referenced without the "`struc`" prefix."* - Note that this statement is not true for C, it is only correct for C++, doesn´t matter what a specific implementation does. https://godbolt.org/z/XzFFv6 – RobertS supports Monica Cellio Feb 10 '20 at 18:46
25

In C, the type specifier keywords of structures, unions and enumerations are mandatory, ie you always have to prefix the type's name (its tag) with struct, union or enum when referring to the type.

You can get rid of the keywords by using a typedef, which is a form of information hiding as the actual type of an object will no longer be visible when declaring it.

It is therefore recommended (see eg the Linux kernel coding style guide, Chapter 5) to only do this when you actually want to hide this information and not just to save a few keystrokes.

An example of when you should use a typedef would be an opaque type which is only ever used with corresponding accessor functions/macros.

Christoph
  • 164,997
  • 36
  • 182
  • 240
12

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 won't work:

struct myStruct; //forward declaration fails

void blah(myStruct* pStruct);

//error C2371: 'myStruct' : redefinition; different basic types
nbro
  • 15,395
  • 32
  • 113
  • 196
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185
11

The following code creates an anonymous struct with the alias myStruct:

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

You can't refer it without the alias because you don't specify an identifier for the structure.

nbro
  • 15,395
  • 32
  • 113
  • 196
PlainOldProgrammer
  • 2,725
  • 5
  • 22
  • 30
6

The typedef, as it is with other constructs, is used to give a data type a new name. In this case it is mostly done in order to make the code cleaner:

struct myStruct blah;

vs.

myStruct blah;
jjnguy
  • 136,852
  • 53
  • 295
  • 323
RC.
  • 27,409
  • 9
  • 73
  • 93
6

The difference comes in when you use the struct.

The first way you have to do:

struct myStruct aName;

The second way allows you to remove the keyword struct.

myStruct aName;
jjnguy
  • 136,852
  • 53
  • 295
  • 323
4

I see some clarification is in order on this. C and C++ do not define types differently. C++ was originally nothing more than an additional set of includes on top of C.

The problem that virtually all C/C++ developers have today, is a) universities are no longer teaching the fundamentals, and b) people don't understand the difference between a definition and a declaration.

The only reason such declarations and definitions exist is so that the linker can calculate address offsets to the fields in the structure. This is why most people get away with code that is actually written incorrectly-- because the compiler is able to determine addressing. The problem arises when someone tries to do something advance, like a queue, or a linked list, or piggying-backing an O/S structure.

A declaration begins with 'struct', a definition begins with 'typedef'.

Further, a struct has a forward declaration label, and a defined label. Most people don't know this and use the forward declaration label as a define label.

Wrong:

struct myStruct
   {
   int field_1;
   ...
   };

They've just used the forward declaration to label the structure-- so now the compiler is aware of it-- but it isn't an actual defined type. The compiler can calculate the addressing-- but this isn't how it was intended to be used, for reasons I will show momentarily.

People who use this form of declaration, must always put 'struct' in practicly every reference to it-- because it isn't an offical new type.

Instead, any structure that does not reference itself, should be declared and defined this way only:

typedef struct
   {
   field_1;
   ...
   }myStruct;

Now it's an actual type, and when used you can use at as 'myStruct' without having to prepend it with the word 'struct'.

If you want a pointer variable to that structure, then include a secondary label:

typedef struct
   {
   field_1;
   ...
   }myStruct,*myStructP;

Now you have a pointer variable to that structure, custom to it.

FORWARD DECLARATION--

Now, here's the fancy stuff, how the forward declaration works. If you want to create a type that refers to itself, like a linked list or queue element, you have to use a forward declaration. The compiler doesn't consider the structure defined until it gets to the semicolon at the very end, so it's just declared before that point.

typedef struct myStructElement
   {
   myStructElement*  nextSE;
   field_1;
   ...
   }myStruct;

Now, the compiler knows that although it doesn't know what the whole type is yet, it can still reference it using the forward reference.

Please declare and typedef your structures correctly. There's actually a reason.

CodeGuru
  • 73
  • 1
  • 4
    I don't believe C++ was ever "a set of includes on top of C". The first implementation, cfront was a preprocessor that translated C++ source code to C source code. And I disagree with your advice about using typedefs for structures, and particularly for pointers. Hiding a pointer type behind a typedef can be dangerous; it's better IMHO to make the fact that it's a pointer explicit by using `*`. In your final example, I'm curious about the rationale for using one name (`myStruct`) for the typedef and another (`myStructElement`) for the struct tag. – Keith Thompson May 07 '16 at 21:44
  • 2
    Much of this is a matter of stylistic preferences. I disagree rather strongly with most of your suggestions (which is not to say you're wrong). See [my answer](http://stackoverflow.com/a/26389105/827263) for a summary of my own preferences (which are shared by many, but certainly not all, C programmers). – Keith Thompson May 07 '16 at 21:45
2

With the latter example you omit the struct keyword when using the structure. So everywhere in your code, you can write :

myStruct a;

instead of

struct myStruct a;

This save some typing, and might be more readable, but this is a matter of taste

shodanex
  • 14,975
  • 11
  • 57
  • 91