Let's analyse your code a bit:
typedef struct nodes
{
int data;
struct node *next;
}node;
This declares and defines struct nodes
, a type with two members, and declares a type alias so we can refer to it only as node
.
Now, in C++, the member declaration struct node *next
automatically forward-declares a type called node
. That then conflicts with your typedef
target node
: it's as if you're trying to give two types the same name.
In C, there is no conflict, because the type called node
can in fact only be referred to as struct node
.
The second snippet worked because, since during parsing of the member declaration struct node
already exists, no new type is forward-declared there … and since all you're then doing is renaming it in the same typedef
statement, C++ doesn't really care, knowing that it's all the same type (struct T
is T
; the difference is in syntax, not in name).
[C++11: 7.1.3/3]:
In a given non-class scope, a typedef
specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [ Example:
typedef struct s { / ... / } s;
typedef int I;
typedef int I;
typedef I I;
—end example ]
[C++11: 7.1.3/6]:
In a given scope, a typedef
specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type. [ Example:
class complex { / ... / };
typedef int complex; // error: redefinition
—end example ]
Of course, in C++, this is all moot and you should just write:
struct node
{
int data;
node* next;
};
You do not need to typedef
-away the elaborated-type-specifier struct
.