This gives an error in C++ but not in C:
typedef struct nodes
{
int data;
struct node *next;
}node;
It gives the following error in C++.
/home/DS cpp/linkedlist.cpp|10|error: conflicting declaration ‘typedef struct nodes node’|
/home/DS cpp/linkedlist.cpp|9|error: ‘struct node’ has a previous declaration as ‘struct node’|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
For it to work in C++ I have to change it to this:
typedef struct node
{
int data;
struct node *next;
}node;
I don't understand why this happens, I want to know the order of execution in both C and C++ so that I can understand it.
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, atypedef
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, atypedef
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
.
The C example you gave should be an error. You're using a tag name (node
) that you haven't defined with struct node
.
Given those two choices, the second is the one to use. I prefer a bit of economy:
typedef struct node_t
{
int data;
struct node_t *next;
} node_t;
In C or C++, the tag names have their own namespace, so there is no problem with using the same name for the tag and the typedef name. In C, this allows you to use either node_t
or struct node_t
to refer to this struct type. C++ will search the tag names for a type name if a declared type name doesn't exist, so the above double-definition isn't needed, but doesn't hurt.
In both languages, the explicit struct node_t
version is required at any point before the type is completely defined, so any self-reference, and any forward references will use the struct
version. I prefer this in header files, mostly because it reduces problems with order of #include
directives.
PS: This does work in either language (see LRIO's answer for pointers into the C++11 Standard) and has been used in enough bilingual and even pure C++ header files that it's unlikely to disappear soon) so it's a very simple approach that just works in either language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With