Here are three methods given in my book:-
1)
struct book
{ char name;
float price;
int pages;
};
struct book b1; b2; b3;
2)
struct book
{
char name;
float price;
int pages;
}
b1, b2, b3;
3)
struct
{
char name;
float price;
int pages;
} b1, b2, b3;
In 2nd method,there is a confusion why the closing brace in structure type declaration is not followed by a semicolon?
The 3rd method doesn't make any sense to me because we don't even declared the name of the structure.
So, How these two methods are valid?
At the time a struct
is defined, you can also define one or more instances of that struct. This is what is happening in both the 2nd and the 3rd examples.
The difference between the two is that one declares three variables of type struct book
at the time that type is defined, while the other declares three variables whose type is an anonymous struct. In the latter case, that means that no other variables of that type may be defined since the struct has no name and does not have an associated typedef
.
The whole construct of
struct {
int field1;
char field2;
// ...
}
is itself a type . So you can use it in variable declarations in the same way you use other types. They are all of the form
<type> <identifier>;
with optionally more identifiers to declare multiple variables at once.
By example:
struct {int x; char y;} bar;
is a valid variable declaration, just as
int bar;
is. Remember newlines don't have any syntactical meaning in C.
With a struct
, you can give it a name (called struct tag ), like this:
struct foo {
int field1;
char field2;
// ...
};
If you do this, you can later use the same struct type by just writing
struct foo
instead of repeating all its fields. That's in fact the most common usage.
TL/DR - C declaration syntax allows all three methods .
Have patience, this is going to take a while.
Let's start with the syntax for a declaration:
declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declaration
declaration-specifiers:
storage-class-specifier declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
The opt
subscript means that the item is optional; IOW, a sequence of declaration specifiers may be followed by a sequence of declarators (or not), a type specifier may be followed by more declaration specifiers (or not), etc.
We also have the following constraint :
A declaration other than a static_assert declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration.
Lovely. What does all that mean?
Basically, a declaration in C has two main parts - a sequence of declaration specifiers (which may include storage class specifiers like static
and auto
, type specifiers like int
, double
, char
, struct foo
, type qualifiers like const
, etc.) and an optional sequence of declarators (basically, variable or function names), each of which may be initialized. For example, in the declaration
static const int *foo[N] = { &bar, &blah, ... };
our declaration specifiers are static const int
, our declarator is *foo[N]
, and our initializer is { &bar, &blah, ... }
.
What we're interested in for the purpose of your question is the type-specifier
, and specifically a struct-or-union-specifier
:
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
atomic-type-specifier
struct-or-union-specifier
enum-specifier
typedef-name
struct-or-union-specifier:
struct-or-union identifieropt { struct-declaration-list }
struct-or-union identifier
The struct-or-union-specifier
has two forms - one where you specify the contents of the struct, and one where you do not.
The identifier
is the tag name of the structure or union; it's how you can refer to that specific type later on (either as part of another declaration, or part of a sizeof
expression, etc).
Note that in the first case, where you're specifying the members of the structure type, the tag name is optional - it's perfectly legal to write a declaration like
struct { int a; int b; } x;
| | |
+---------+------------+ |
| V
V declarator
type-specifier
The struct definition itself is a type specifier, just like int
or double
, etc.
However, without a tag name, you cannot refer to this same structure type in future declarations. You can certainly repeat the definition for another variable:
struct { int a; int b; } y;
but the types of x
and y
will be distinct - the compiler considers each struct
definition to be a different type, even though they have the same contents.
Now, remember from the general declaration syntax above, the list of declarators in a declaration is optional . This is what allows us to declare a structure with just a tag name (although per the constraint above, you must include the tag name if you are not declaring a variable of this type):
struct foo { int a; int b; };
| |
+-----------+--------------+
|
V
type-specifier
We've defined the struct type and given it the tag name foo
; we can declare objects of this type as
struct foo x;
struct foo y;
Because from the syntax above:
struct foo x;
| |
+---+----+
|
V
type-specifier
This time, x
and y
are considered to be the same type.
We can also declare a variable at the same time we define the struct:
struct foo { int a; int b; } x; | | +----------+---------------+ | V type-specifier
struct foo y; | | +----+---+ | V type-specifier
The first declaration creates the struct foo
type and declares x
to be a variable of that type. The second declaration uses the previously defined struct foo
type to declare a variable y
.
Basically, C declaration syntax, especially with respect to structures, unions, and enums, is fairly flexible, and all of the methods listed in your book are equally valid.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.