First off, let's be clear here: a typedef
isn't a declaration of a variable. It simply aliases a new type name to an existing type specifier.
typedef <type specifier> new_type_name;
So what's going on here can certainly be deceiving to the untrained eye.
struct node
itself is a struct
called node
with the two properties int data
and a struct node *next
.
I'll go more into next
in a moment, but for now this is simple enough.
Then, the surrounding typedef
takes that struct and gives it the name node
. Why is this, you might ask?
This is due to the fact that in C (unlike C++) using structs by their tag name requires prefixing the type with struct
.
struct Foo {
// ...
};
Foo bar; // ERROR
struct Foo bar; // OK
Using a typedef, we alias the struct with a typename, called node
. This example should make it a bit more clear.
typedef struct Foo {
// ...
} FooType;
Foo bar; // ERROR
struct Foo bar; // OK
FooType bar; // OK
struct FooType bar; // ERROR
Keep in mind you can define structs without tags, and thus typedef
them.
typedef struct {
// ...
} FooType;
FooType bar; // OK
Though I'll explain why you can't do this in your example.
The property struct node *next
in your example is an incomplete type. Incomplete types, simply put, are types that have been declared (given a name and a type, i.e. struct node;
), but not defined (given a 'body', i.e. struct node { int foo; };
).
Incomplete types cannot be used until they are defined, unless you're pointing to them.
struct Foo;
struct Foo bar; // ERROR: Foo is not defined.
struct Foo *bar; // OK - it's just a pointer. We know the size of a pointer.
struct Foo {
// ...
};
struct Foo bar; // OK - it's defined now.
So by the type struct node *next
is declared, we already have the declaration of struct node
but not the definition, which makes a pointer to struct node
possible.
You can also infer, too, that using struct node
directly would not work:
struct node {
struct node next; // ERROR - `struct node` becomes infinitely big
struct node *next; // OK - a pointer is usually 4/8 bytes (we at least know its size at this point)
};
To answer your last three questions:
What [does] typedef node * nodepointer;
[point] to[?]
Nothing. It's just an alias (a label, or a 'nickname') to another type. It simply says that the type nodepointer
is really a node *
.
This also means anything that requires a node *
can thus use a nodepointer
, and vice versa.
Is it necessary to use typedef
in this case?
Not necessary, no. You could just as well use node *
everywhere instead of nodepointer
. Most coding standards frown upon typedef
ing types to their pointer types (like your example) because it adds confusion to the code base (as you have demonstrated by this very question! :))
Is [the] expression node * nodepointer;
not equal?
Nope. Again, remember typedef
simply specifies another way to reference the same type. It doesn't actually create any memory, rather gives a new name to an existing type.