Typedef struct wrong declaration? - c

I referred to the tutorial below and later realized it is wrong way of declaring struct using typedef.
typedef struct
{
char name[namesize];
char address[addresssize];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
} PersonalData;
then declare:
PersonalData x;
However, I believe the right way is
typedef struct personaldataStruct
{
char name[namesize];
char address[addresssize];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
} PersonalData;
then declare:
PersonalData x;
Did the author mislead me? or both ways are correct? please confirm.
Here is the tutorial http://www.iu.hio.no/~mark/CTutorial/CTutorial.html

There's nothing formally "incorrect" about either approach.
The former declares a tag-less struct type and a typedef name PersonalData for that struct type. The latter declares a struct type struct personaldataStruct and a synonymous typedef name PersonalData for that struct type. The personaldataStruct part of the declaration is commonly referred as a "struct tag".
As long as you use PersonalData typedef name for referring to that struct type, as in
PersonalData x;
you will not see any difference between the two declarations. In both cases x will be declared identically.
The latter approach provides you with an alternative way of referring to the same struct type - struct personaldataStruct - if for some reason you will wish to do so. E.g. when using the latter declaration, you can also declare your x as
struct personaldataStruct x;
which is exactly equivalent to the PersonalData x; declaration.
Personally, I prefer to use the approach with struct tag, since it provides me with alternative way of referring to the type, which might come handy in some situations (for example, when the struct type has to refer to itself). But in most non-self-referential cases one will be perfectly fine with the former approach.

Both are correct. The only real problem with the first form (without the tag) is that, because the typedef name doesn't become visible until the end of the definition, there's no way to refer to the structure from within its own definition. That's a common requirement; for example, a node in a linked list, tree, or other graph-like data structure commonly needs to point to other objects of the same type.
Since struct tags and typedef names are in different namespaces (not to be confused with C++ namespaces), there's no need for them to be distinct. It's perfectly acceptable to use the same identifier for both:
typedef struct PersonalData {
/* ... */
struct PersonalData *next;
} PersonalData;
Or, as long as you're going to have both a tag and a typedef anyway, you can forward declare the typedef:
typedef struct PersonalData PersonalData;
/* At this point, "struct PersonalData is an incomplete type. */
struct PersonalData {
/* ... */
PersonalData *next;
};
/* And now "struct PersonalData" is a complete type. */
(But a misspelling can leave you with a typedef that still refers to an incomplete type that's never completed, which can trigger errors that can be difficult to track down. Copy-and-paste is your friend.)
And there is another alternative. The type you've defined already has a name: struct PersonalData. All the typedef does is give that same type a different name. It's nice to be able to use a single identifier as a type name, but it's really not necessary. My own preference is to omit the typedef altogether, and just refer to the type as struct PersonalData:
struct PersonalData {
/* ... */
struct PersonalData *next;
};
struct PersonalData *head;
struct PersonalData fred;
Unless PersonalData is meant to be an opaque type (meaning that code that uses it doesn't need to know that it's a struct), there's some advantage in being explicit.
Plenty of people strongly disagree with me on this point, and really like using typedefs for structures, as you'll probably see in comments. There's nothing wrong with using typedefs like this; it's just not necessary. You should be prepared to read code written by others using either style.

Related

Why are typedef names used twice in struct declaration in C?

While researching queues in C, I came across an example similar to the below. Why is the struct named both at the beginning of the curly braces and after? Why is struct type used again inside of the struct when adding an item of the same type? Are these things redundant or is there a point?
typedef void* vpoint_t;
typedef struct queue_item_t{
vpoint_t void_item;
struct queue_item_t* next;
} queue_item_t;
typedef struct queue_item_t { // 1
vpoint_t void_item;
struct queue_item_t* next; // 2
} queue_item_t; // 3
First of all, note that this entire statement is defining a typedef.
3) Is saying that the new type we are in the process of defining (via typedef) is going to be named queue_item_t.
1) The name of the structure (which is being given a new name, as we go), is named struct queue_item_t. That's it's full name, including struct at the front.
2) Because the new type doesn't yet exist (remember, we're still in the process of defining it), we have to use the only name it has thus far, which is struct queue_item_t, from 1).
Note that you can have anonymous struct definitions, which allow you to omit the name from 1). A simple example:
typedef struct {
int x, y, z;
} vector3;
In your example however, since we need the structure to be able to refer to itself, the next pointer must have a type that's already defined. We can do that by forward declaring the struct, typedefing it, then defining the struct using the typedefd type for next:
struct _queue_item; // 4
typedef struct _queue_item queue_item_t; // 5
struct _queue_item { // 6
vpoint_t void_item;
queue_item_t* next; // 7
}
4) Declare that struct _queue_item exists, but don't yet provide a definition for it.
5) Typedef queue_item_t to be the same as struct _queue_item.
6) Give the definition of the structure now...
7) ...using our typedef'd queue_item_t.
All that being said... In my opinion, please don't use typedefs for structs.
struct queue_item {
void *data;
struct queue_item *next;
}
is simple and complete. You can manage to type those six extra characters.
From the Linux Kernel coding style:
Chapter 5: Typedefs
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.
There are exceptions, which you can read about.
Some recent related questions:
Why use an opaque “handle” that requires casting in a public API rather than a typesafe struct pointer?
Does casting a pointer back and forth from size_t or uintptr_t break strict aliasing?
Let's change the declaration a little bit to make the discussion easier to follow:
typedef struct queue_item {
vpoint_t void_item;
struct queue_item* next;
} QueueItemType;
C supports several different name spaces; one name space is reserved for tag names on unions, structures, and enumeration types. In this case, the tag name is queue_item. Another name space is reserved for regular identifers, including typedef names like QueueItemType.
The next member is being used to point to another instance of type struct queue_item (i.e., the next item in the queue). It's declared as a pointer to struct queue_item for two reasons:
A struct type cannot contain an instance of itself; for one thing, the type would have to be infinitely large (struct queue_item contains a member next, which is a struct queue_item that contains a member next, which is a struct queue_item that contains a member next, ad infinitum);
The struct type definition isn't complete until the closing }, and you can't declare an instance of an incomplete type. However, you can declare a pointer to an incomplete type, which we do below:
struct queue_item *next;
Why not use QueueItemType *next; instead of struct queue_item *next? Again, the struct type definition isn't complete at the point next is being declared; the typedef name QueueItemType doesn't exist yet. However, the tag name queue_item is already visible to the compiler, so we can declare pointers using the type struct queue_item.
Since tag names and typedef names occupy different name spaces, it's possible to use the same name for both the tag name and the typedef name without a collision. The compiler disambiguates between the two by the presence of the struct keyword.
First, I suggest to NEVER use a struct name and identical type name. Use typedef struct QUEUE_ITEM {...} queue_item_t;
As to the question: if you want to make a "recursive data structure", that is, a data structure that has pointers to instances of itself, then you must be able to tell the compiler "This field is a pointer to one of ourselves. You don't know what we look like yet completely, because I am still defineing it, so just reserve space for a pointer". To do that you declare
struct T {
...
struct T *ptr;
....
};
With the final } queue_item_t; you create a new name for the structure.
"struct foo {...} " is one thing. It defines a struct, you need to type "struct foo" in every place you use it.
"typedef ... foo" defines a new type, so you just type "foo" where you use it.
"typedef struct foo {...} foo" is an idiom so you can use both, most probably just "foo" to save keystrokes and visual pollution.

Structure declaration in c with identifer

I am try to understand this C code:
typedef struct _IntElem *IntList;
typedef struct _IntElem { int head; IntList tail;} IntElem;
I understand that it defines a recursive type, a list. However I don't understand the way it is declared. What I understand is the second line, we define a structure named IntElem which consists of an integer and an IntList. But what is the _IntElem in this declaration?
The first line allocates memory for the list?
The first line
typedef struct _IntElem *IntList;
is to just create a typedef or an alias for struct _IntElem *. The alias is named IntList. FWIW, at this point of time, the definition of struct _IntElem need not to be known to the compiler.
The second line
typedef struct _IntElem { int head; IntList tail;} IntElem;
Actually defines an user-defined type _IntElem, with two members, head as int and tail as IntList(typedefed earlier)
typedef the type to IntElem.
Please Note: There is actually no variable created, for either of the type (s) (I'm not talking about the member variables, of course, they are part of the definition). So, there is no memory allocated , as such.
So, to be explicit
But what is the _IntElem in this declaration?
the _IntElem is the name of the user-defined data type. However, in some cases, it is optional. for example,
typedef struct { char name [32]; int age; float salary;} employee;
is both perfectly fine and legal, except the fact, in this case, we're creating an alias employee to an unnamed data type.
In C, if we have:
struct X
{
stuff....
};
then X is called a struct tag. It means that struct X is the name of a type. X on its own is not the name of a type. In fact X on its own behaves like any other undeclared identifier; this struct definition only defines the specific usage struct X.
We might say that struct tags live in a different namespace to other identifiers (not to be confused with C++ namespaces!)
Sometimes people don't like typing struct X everywhere. So they use typedef (which, confusingly, means to create a type alias) in order to make a single identifier that names the type:
typedef struct X SX;
means that SX is a type. But since struct tags are in their own namespace, you could even write:
typedef struct X X;
which means that X on its own refers to the same type as struct X does.
Hopefully you understand the code you are looking at now. I think it would have been clearer to write:
struct IntElem
{
int head;
struct IntElem *tail;
};
with the optional addition to save typing:
typedef struct IntElem IntElem;
Pointer typedefs are evil, so IntList can be omitted entirely. Possibly you could keep it around to use as an opaque type for the users of your list, but you should avoid using it during your list implementation.

Declaring a structure: typedef struct name name;

We all know how to declare a structure in C:
struct Label1{ /* variables */ } Label2; // As I learned
But I want to know why this code works without declaring 'struct name':
typedef struct name s_name;
Or is in fact, does typing the code
struct name;
mean that I declared 'struct name' as a void structure or something like this?
Example of code:
typedef struct Data Data;
struct Data{ /*variables*/ };
If in the first line struct Data is declared as a void one, then in the second it's like I'm redeclaring it with members.
What is the explanation for this point?
Something like:
struct MyStruct;
Is called a forward reference. It creates an incomplete type and tells the compiler there will be a type of that name (and it's a struct - it works likewise for unions), and the details "follow later". Of such a type you cannot define variables, until you complete the type.
typedef struct MyStruct MyType;
Will just define the type name to be that struct. This is still an incomplete type.
However, you can take a pointer to an incomplete type:
MyType *my_t_pointer;
struct MyStruct *my_s_pointer;
This is useful for a struct to have pointers to objects of the same type when you provide the full declaration, "completing" the type:
struct MyStruct {
struct MyStruct *next;
};
Actually this is the only way to create nodes for lists, trees, and all other recursive data-structures. This is a major part of C programs (sometimes hidden).
Also, this mechanism is used to hide implementation details. Functions in the header need only know the struct exists to take/pass pointers to it. The use of these functions need not to know the details of the struct (but this way it cannot allocate it, so the module has to cover all aspects which need to know details on the struct). The full declaration is only inside the implementation file of the module.
These pointers are called "opaque" as one cannot "look through", i.e. access the fields of the struct as they are simply not known to it.
my_module.h:
struct MyStruct;
extern void my_init(struct MyStruct *obj);
my_module.c:
struct MyStruct {
int f1;
...
};
my_init(struct MyStruct *obj)
{
...
}
The typedef declares s_name as an alias for struct name so that you can declare variables, e.g.:
s_name *sptr;
The line
struct name;
declares that there is a struct type called name without defining its content. This is usually done in order to be able to declare variables as pointers to the struct type. You cannot declare variables of the actual struct type until it has been defined.

Just don't understand the point of these typedefs

When trying to discover something in the code of some open source C projects, I often see this kind of typedef:
typedef struct _StructA StructA;
typedef struct _LinusTorvalds LinusTorvalds;
Why not directly define and use StructA, just StructA, instead of defining _StructA then "typedef" it?
What's the point of this "_" technique?
In C, a struct must be used as:
struct _StructA my_variable;
…i.e., you must type struct not only when you define the struct, but also every time you use it. The typedef eliminates the typing of struct when you use it (but not when you define it: there is no way to eliminate that). With a typedef then, declaring an instance of the struct becomes:
StructA my_variable;
Now, that doesn't completely explain the _StructA/StructA business in the defining of the struct/typedef, as you can do this:
typedef struct {
...
} StructA;
…here, we take an anonymous struct and immediately feed it to typedef. But using this method, you can't use the struct inside itself, as it doesn't (yet) have a name. For that, you need something like:
typedef struct _Foo {
int data;
struct _Foo *next;
} Foo;
In C, when you define a struct type:
struct StructA {
int foo;
double bar;
};
the type's name is struct StructA, not just StructA. (C++ lets you refer to the type as just StructA; C++ is a different language.
If you insist on having a one-word name for it, you can use a typedef (which, we should note, creates a new name for an existing type, not a new type):
typedef struct StructA StructA;
Now you can refer to the type either as StructA or as struct StructA.
These can be combined into a single declaration:
typedef struct StructA {
int foo;
double bar;
} StructA;
Note that I used the same identifier for the struct tag and for the typedef. Since they're in different namespaces, this is perfectly valid.
On the other hand, my own preference is to omit the typedef altogether, and just refer to the type as struct StructA.
Incidentally, the names _StructA and _LinusTorvalds in your question are reserved to the implementation, and should not be used in your own code. In general, identifiers starting with an underscore should be avoided. (It's not uncommon to use such identifiers, but it's wrong, unless the code is part of the C implementation itself.)
To summarize: The typedef is necessary only if you want to have a one-word name for the type (which isn't really required) -- and if you do use a typedef, there's no real reason to use different identifiers for the typedef and the struct tag.
It provides the convenience of not using the struct keyword everytime you declare variables of the structure.
Without typedef:
struct _StructA obj;
With typedef:
StructA obj;
It could reduce the dependency to a certain data structure. E.g. if you ever want to use StructB (maybe containing more fields) instead of StructA, you need to change just one line, not hundreds.

Why often a struct's tagName differs from the typedef's name?

Sometimes I see code like this (I hope I remember it correctly):
typedef struct st {
int a; char b;
} *stp;
While the usual pattern that I familiar with, is:
typedef struct st {
int a; char b;
} st;
So what's the advantage in the first code example?
You probably mean this:
typedef struct ST {
/* fields omitted */
} *STP;
The asterisk is at the end of the statement. This simply means "define the type STP to be a pointer to a struct of this type". The struct tag (ST) is not needed, it's only useful if you want to be able to refer to the struct type by itself, later on.
You could also have both, like so:
typedef struct {
/* fields omitted */
} ST, *STP;
This would make it possible to use ST to refer to the struct type itself, and STP for pointers to ST.
Personally I find it a very bad practice to include the asterisk in typedefs, since it tries to encode something (the fact that the type is a pointer) into the name of the type, when C already provides its own mechanism (the asterisk) to show this. It makes it very confusing and breaks the symmetry of the asterisk, which appears both in declaration and use of pointers.
It's a habit that stems from the time when typedef names and struct tagnames were in the same namespace. See http://blogs.msdn.com/oldnewthing/archive/2008/03/26/8336829.aspx
I think you are talking about :
typedef struct{
int a;
char b;
} object, *objectPointer;
This means that (new) type objectPointer is a pointer to struct (object) defined above. Its easy to declare pointers to object struct this way. For instance,
objectPointer A = (objectPointer)malloc(sizeof(object));
A->a = 2;
Now, A is a pointer to struct object and you can access its variables as described above.
In case, objectPointer was not defined,
struct object *A = (struct object *)malloc(sizeof(object));
A->a = 2;
So, I guess objectPointer is more intuitive and easy to use.
I hope that the first code would say a compiler error ,
I see no good reason for the typedef name be different from the tag name.
Now, the reason for which the tag name needs to be typedefed if you don't want to use
struct tag v;
but
tag v;
is probably an historical one. For as long as I remember, C had typedef but I don't know if it was true when struct have been introduced (handling of typedef is a nuisance in the C grammar). In the old code I've seen, using typedef for struct isn't done, and there are things like unix
struct stat;
int stat(const char*, struct stat*);
which would break with an automatic typedef. One those are introduced, changing is quite difficult (yes, C++ has automatic typedef but C++ has special wording to handle that case of overloading and it would be yet another complication).

Resources