Typedef struct in C Vs C++

24,867

Solution 1

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.

Solution 2

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.

Share:
24,867
Achyut Rastogi
Author by

Achyut Rastogi

BY Day I am a student, and by night I am still a student, I don't know how to do any magical transformations yet! I am on my way to becoming an open-source contributor and my favourite language is Python. For pass time I wander on stack overflow reading answers, watch animé, read about latest trends in open-source, play games and some competitive coding in C++ all about in equal portions. Trying to add open source to the mix!

Updated on August 10, 2020

Comments

  • Achyut Rastogi
    Achyut Rastogi over 3 years

    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.