Related
This question already has answers here:
Why should we typedef a struct so often in C?
(15 answers)
Closed 6 years ago.
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;
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;
}
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.)
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.
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;
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.
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.
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
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.
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;
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;
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.
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
This question already has answers here:
Why should we typedef a struct so often in C?
(15 answers)
Closed 6 years ago.
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;
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;
}
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.)
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.
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;
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.
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.
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
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.
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;
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;
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.
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
Short Question
Is there a proper or preferred way to to use typedefs of structs and enums in C?
Background
I have been working on a code base that has had several people / companies working on it and I have come across different implementations of typedefs. According to Wikipedia they all appear to have the same function. I guess I'm trying to understand if there are subtile differences or gotchas between them. The same usages and question applies to typedefing an enum.
// I tend to use this if I need to create an
// alias outside the defining module.
typedef struct obj obj_t;
struct obj
{
UINT8 val;
};
// I started to use this format to alias objects
// within the same module (both private and
// public definitons). This is also how
// several colleagues use them.
typedef struct obj_t
{
UINT8 val;
}obj_t;
// This is how I now typically format the aliases
// for both public and private definitions.
typedef struct
{
UINT8 val;
}obj_t;
// I just ran into this one. While makes sense
// how it works, it wasn't inherently better or
// worse then the formats above. Note the different
// container names.
typedef struct obj_t
{
UINT8 val;
}obj;
They are all basically the same, in that they all define obj_t as a type alias for the structure.
The difference is when you define the name of the structure (e.g. struct obj ...) is that you can then also use struct obj myStructure; This is needed if you want to reference the structure inside it self (like when creating a linked list for example). If you do the typedef before the actual structure (like in your first example) then you can of course use the typedef'd name inside the structure as well.
Another subtile difference between your declarations is version 2 to 3. In 3, you use a typedef of an unnamed struct which is will give you an implicit cast error when you are going to cast it to let's say 2.
typedef struct obj obj_t;
struct obj
{
UINT8 val;
};
Writing the typedef before lets you use it inside the structure.
typedef struct obj_t
{
UINT8 val;
}obj;
typedef struct obj_t
{
UINT8 val;
}obj_t;
these two are for when you need to declare variables using either "struct obj_t" or "obj_t". I prefere using a t_ or _t for typedefs (more explicit), but it's really just a coding style matter, no technical chose to use one instead of the other.
typedef struct
{
UINT8 val;
}obj_t;
Here you can only use the typedef since the structure has no name. Therefore you can't declare, inside your structure, a variable of this type.
I wouldn't answer your question, but would instead suggest to consider what Linux kernel coding style has to say on the matter of typedefs. See "Chapter 5: Typedefs". Excerpt:
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.
Read on for the suggested exceptions.
all given examples of typedefing a structure informs the same thing.Currently peoples are following all this either because of employer's style guide or for customer specific coding style.you have already given all possible struct type so i am adding ENUM only what you asked for
typedef enum season_t { SPRING, SUMMER, FALL, WINTER } Season;
for more standard answers you can look into below given link
http://www.montefiore.ulg.ac.be/~piater/Cours/Coding-Style/
I'm curious what the difference here is when typedefing an enum or struct. Is there any difference semantically between these two blocks?
This:
typedef enum { first, second, third } SomeEnum;
and this:
enum SomeEnum { first, second, third };
typedef enum SomeEnum SomeEnum;
Same deal for structs. I've seen both in use, and they both seem to do the same thing in C or Objective-C. Is there a real difference or is it just a preference for which style you can use?
The difference is that the second approach declares a type named enum SomeEnum and also declares a typedef-name SomeEnum - an alias for that type. It can actually be combined into the equivalent one-liner
typedef enum SomeEnum { first, second, third } SomeEnum;
which makes it rather obvious that the only difference between the two approaches is whether there's a name after the enum keyword. With the second approach, you can declare object of that enum type by using either SomeEnum e or enum SomeEnum e, whichever you prefer.
The first approach only declares the typedef-name SomeEnum for an originally anonymous enum type, meaning that you are limited to SomeEnum e declarations.
So, as long as you only use the typedef-name SomeEnum in your declarations, there will be no difference between the two. However, in some cases you might have to use the full original name of the type enum SomeEnum. In the first approach that name is not available, so you'll be out of luck.
For example, if after the above declaration you also declare a variable named SomeEnum in some nested scope
int SomeEnum;
the name of the variable will hide the typedef-name of the enum, thus making this declaration illegal
SomeEnum e; /* ERROR: `SomeEnum` is not a type */
However, if you used the second approach when declaring your enum, you can work around this problem by using the full type name
enum SomeEnum e; /* OK */
This would not be possible if you used the first approach when declaring your enum type.
When used with structs, the name after the struct is a must when you need a self-referencing type (a type that contains a pointer to the same type), like
typedef struct SomeStruct {
struct SomeStruct *next;
} SomeStruct;
Finally, in the second approach the typedef name is totally optional. You can simply declare
enum SomeEnum { first, second, third };
and just use enum SomeEnum every time you need to refer to this type.
Yes, there is a semantic difference. The second snippet declares a tag identifier, but the first doesn't. Both declare an ordinary identifier.
That means that for the first, this code is not valid, but for the second, it is:
enum SomeEnum foo;
As far as i know, there is no other semantic difference between them in your code. For structs and unions, the second form, maybe combined with the typedef in one declaration, is needed for recursive types
typedef struct node {
struct node *parent; // refer to the tag identifier
} node;
The ordinary identifier is not yet visible in the struct's specifier, and thus you need to refer to the struct by the already declared tag identifier. Tag identifiers are referred to by prepending them by "struct", "union" or "enum", while ordinary identifiers are referred to without a prefix (thus the name "ordinary").
Besides separating the identifiers that refer to structs, unions and enumerations from those that refer to values, tag identifiers are also useful for creating forward declarations:
/* forward declaration */
struct foo;
/* for pointers, forward declarations are entirely sufficient */
struct foo *pfoo = ...;
/* ... and then later define its contents */
struct foo {
/* ... */
};
Typedef names can't be declared repeatedly at the same scope (as opposed to C++ where they can), and they need to refer to an existing type, so that they cannot be used to create forward declarations.
The only real difference is that in the second case, you can use something like:
enum SomeEnum x;
whereas the first only supports:
SomeEnum x;
To people who've been writing C a long time, defining a struct without the struct keyword often "feels" strange...
The first form creates an anonymous enum type and creates a SomeEnum alias to it.
The second form creates both a enum SomeEnum type and a SomeEnum alias to it.
(In C, there are separate namespaces for types. That is, struct Foo is different from enum Foo which is different from Foo.)
This is more important for structs than enums since you'd need to use the second form if your struct were self-referential. For example:
struct LinkedListNode
{
void* item;
struct LinkedListNode* next;
};
typedef struct LinkedListNode LinkedListNode;
The above wouldn't be possible with the first form.
For structs there's a real difference that isn't simply about naming.
This is valid C:
struct SomeEnum { struct SomeEnum *first; };
This is not:
typedef struct { SomeEnum *first; } SomeEnum;
Adding to user207442's comment, it's possible for a source code module to declare variables of type "struct foo *" without ever having a definition for the struct. Such a module will not be able to dereference such pointers, but may pass them to and from other modules.
For example, one could have a header file define a type "USERCONSOLE" using "typedef struct _USERCONSOLE *USERCONSOLE;". Code that #include's that header file could have variables of type USERCONSOLE, and pass such variables to/from modules that know what a _USERCONSOLE really is, without the header file having to expose the actual definition of the structure.
This question already has answers here:
Why should we typedef a struct so often in C?
(15 answers)
Closed 6 years ago.
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;
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;
}
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.)
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.
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;
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.
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.
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
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.
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;
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;
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.
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