Related
First, from this:
static struct foo1 { //private struct, just for this file
int a;
};
int main (void) {
struct foo1 a = {10};
return 0;
}
question number 1
I will get warning:
warning: useless storage class specifier in empty declaration
};
What does it mean? Why is static "useless storage class specifier"? In other context (static local var in function, or global static, which I wanted to apply for the struct foo1, it would work).
question number 2
#include <stdbool.h>
static struct s_t{ //private struct (for this file only)
static bool is_there = false; // defaul (pre-defined) value for all instances
int value;
};
int main (void) {}
Why is not possible to have static, predefined value for all vars of type struct s_t in c? I just wanted to simulate the same functionality as is in function static local var -> preserve value across multiple calls, in that sense, I wanted have one member (bool is_there in this case) that preserve value across each var of type struct foo1 (instance of it). So why it is not possible?
question number 3
Also, can someone explain the error (in more general sense) from it:
error: expected specifier-qualifier-list before ‘static’
EDIT:
from comments, I do not really understand the concept of storage class, I know only from asm, there is data/text/bss segments, so does it mean static var has address in read-only part of memory? Or what is the concept of storage class in c related to asm?
Because static struct foo1 { ... is just a struct definition, not a variable. You should add static when you declare the instance of the struct. I prefer this style:
typedef struct {
int a;
}foo_t;
static foo_t a = {10};
Because C simply doesn't have static member variables like C++ does. In C, it's pretty useless to add storage- or type specifiers to a single struct member. Put it on the allocated variables instead.
TL;DR it's just not making any sense of your syntax since you can't have static there. Unless you are terribly interested about language grammar, there's nothing else to it.
static is a storage-class specifier and const etc are type qualifiers and int etc is a type specifier. The term specifier-qualifier list comes from formal C grammar of structs, which isn't terribly interesting to read unless you are making a compiler. When declaring a struct member you have two options (C17 6.7.2.1):
specifier-qualifier-list:
type-specifier specifier-qualifier-list(opt)
type-qualifier specifier-qualifier-list(opt)
static doesn't fit the bill of either, being a storage-class specifier, so the compiler is saying "what! this is not a specifier-qualifier list where I expected to find one, where is it?"
(And yeah it's recursive, so you can have multiple of type-specifier or type-qualifier such as const long const const int value;. Because C stands for Crazy.)
because struct is like a type or an object, when you declare a static member in C, it would be like:
static int a = 0;
In this case "int" is like the struct type you declared, so if you want to create a struct static member just do like this:
static s_t a;
static struct foo1 { //private struct, just for this file
int a;
};
The static declaration specifier only applies to object or function declarations, not type definitions. All you're doing in that statement is creating the struct foo1 type. Had you written something like
static struct foo1 {
int a;
} foo;
Then the object foo would be declared static.
If you declare the type within the .c file, it will only be visible within that .c file. The only way to make the type visible to multiple .c files is to declare it in a header and #include that header in each file that needs it.
Why is not possible to have static, predefined value for all vars of type struct s_t in c?
Because C struct types are simply not that sophisticated - they're just a way to define a data item with multiple attributes. The language doesn't provide any way to have members that are common across all instances of the type.
Remember that C is a product of the early 1970s and was originally developed to implement the Unix operating system - it was designed to be small, portable, and fast. A lot's been added to it over the last 40-some-odd years, but nothing that really changes the core philosophy of the language.
Well, its quite evident that you will get the warning. The reason is simple! You are trying to assign a Storage Class to the struct definition.
However, storage classes are applicable to variable declarations. Therefore, you are getting the prompt.
If you still wish to employ the static storage class, then you can do so with any variable, preferably, any instance 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
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
I have a question about the member variables of static struct in C language.
Someone said we can declare a static struct, but in C, struct do not have the static members like class in C++, what does this mean? If I declare a static struct, what is the status of the members variable? can some one help me on this?
Note that a static struct itself is different from a static member of a struct. While you can declare a static struct variable:
static struct MyStruct s;
you can't define a struct type with a static member:
struct MyStruct {
static int i; // <- compiler error
};
The reason for this is that in C, a struct is a type - declaring a type of which a member variable is always the same instance (i. e. static) for multiple instances of that type is simply nonsense. In C++, structs are in reality classes (they only differ in the default visibility scope of members), and in C++ the static keyword means something else in this case. It means a class method - but since C doesn't have classes and methods, this doesn't make sense and is invalid in C.
Lesson learned: C++ is not C.
static in C means:
There shall only be one instance of this variable in the program.
The variable should be valid throughout the whole duration of the program execution.
The variable shall be initialized before main() is executed. If the programmer initializes a variable explicitly, then it should be set to this value. Otherwise it should be set to zero.
The variable (or static function) shall only be accessible from the scope it is declared inside. If declared at file scope (global), then it is only accessible in the same .c file.
In C++, there is also one additional meaning:
A static member variable or member function shall only be allocated once, no matter how many instances of a class that are allocated.
I have a question about the member variables of static struct in C language.
Someone said we can declare a static struct
Correct/legal:
// (global scope)
static struct t_struct {
int a;
} THE_STATIC_VARIABLE;
but in C, struct do not have the static members like class in C++
// (global scope)
struct t_ill_struct {
static int a; // << ill-formed in C, but valid in C++
};
what does this mean? If I declare a static struct, what is the status of the members variable? can some one help me on this?
Using the above example, it means that THE_STATIC_VARIABLE will have static storage. The following are equivalent:
A
// (global scope)
static struct t_struct {
int a;
} THE_STATIC_VARIABLE;
B
// (global scope)
struct t_struct {
int a;
};
static struct t_struct THE_STATIC_VARIABLE;
That is to say, every translation which sees THE_STATIC_VARIABLE's definition will get its own copy.
If you want the same effect as a static C++ member, you will have to declare it in another scope -- outside of a struct's declaration:
// file.h
// (global scope)
struct t_struct {
int a;
};
extern struct t_struct THE_GLOBAL_VARIABLE;
// file.c
struct t_struct THE_GLOBAL_VARIABLE;
Now we really have exactly one, like in C++.
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