Reputation: 4948
Let's say I define a struct in C. If I declare an instance of that struct, it's necessary that I include the 'struct' keyword in front of it.
// Define struct
struct Book {
char title[50];
char author[50];
char subject[100];
int book_id;
};
// Instantiate struct
int main()
{
struct Book myBook;
}
My question: why is it necessary for the struct keyword to precede any instantiation of the struct? It seems like the compiler would have plenty of information to deduct that 'Book' is a struct.
I realize you can get around this by using a typedef, but that really just seems like boiler plate code for something the compiler should already know.
Upvotes: 3
Views: 403
Reputation: 60163
With the current arrangement, you could have both struct Book
and a global/local symbol named Book
, which doesn't need to be related to struct Book
. struct stat
existing alongside a function named stat
is a nice example this feature being used in POSIX.
Clearly, you could automate the typedefing as C++ has done (and thereby lose the possibility of having a perhaps unrelated Book
and struct Book
in the same scope), but I guess that not automating it makes the grammar perhaps neater, because then if you don't use typedef
s at all, you've got a basically context-free grammar, whereas with typedef
s (explicit or implicit) a context of currently valid typedef
ed types has to be maintained by the parser.
Personally, I prefer automated typedef
ing to the possibility of having a global scope coexist with a struct tag of the same name, and so I do:
#define Struct(Nm,...) typedef struct Nm Nm; struct Nm __VA_ARGS__
#define Union(Nm,...) typedef union Nm Nm; union Nm __VA_ARGS__
#define Enum(Nm,...) enum Nm __VA_ARGS__; typedef enum Nm Nm
Struct(Book,{
char title[50];
char author[50];
char subject[100];
int book_id;
});
(You may want to use it alongside a naming convention that lets you know you're dealing with a struct/union/enum (e.g., _s
as in book_s
)).
Upvotes: 1
Reputation: 311156
Due to using the keywords struct, union and enum names for these types can form their own namespace that will not conflict with names of other entities.
For example
#include <stdio.h>
int main(void)
{
struct Book
{
const char *Book;
} Book = { "The first favorite book" };
struct Book otherBook = { .Book = "The second favorite book" };
puts( Book.Book );
puts( otherBook.Book );
return 0;
}
Upvotes: 1