1

keep getting this error even though i tried to switch places of the structs so they will be declared in the right place.. seems to be the right order this way, but still getting this error. what seems to be the problem ?

typedef struct YListNode {
    int Yval;
    YListNode *next;
}YListNode;

typedef struct YList {
    YListNode *head;
    YListNode *tail;
}YList;

typedef struct XListNode {
    XListNode * prev;
    int Xval;
    YList yList;
    XListNode *next;
}XListNode;

typedef struct List {
    XListNode *head;
    XListNode *tail;
}List;
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Yuval Elmo
  • 25
  • 4
  • 1
    Because the `typedef` is not finished, you canot use the typedef'd name in the struct being defined: `YListNode *next;` is invalid. But you can use the `struct` name of it: `struct YListNode *next;` – Paul Ogilvie Apr 09 '20 at 12:44
  • Try to use the forward declaration of the structures you are defining, reference [here](https://en.cppreference.com/w/c/language/struct). – campescassiano Apr 09 '20 at 12:45
  • It is not a good idea (confusing) to have both `struct YListNode` and `YListNode`. A good solution is to have the typedef'd name prefixed with a small `t`, meaning "type", e.g. `struct YListNode {...} tYlistNode;` – Paul Ogilvie Apr 09 '20 at 12:46
  • You might tell us which compiler prints that message and if there is a more descriptive text besides the plain number. – Gerhardh Apr 09 '20 at 14:56

2 Answers2

2

The order of struct definition is not the issue, rather it has to do with using an as yet undefined typedef to define a struct member...

In this declaration:

typedef struct YListNode {
    int Yval;
    YListNode *next;
}YListNode;

The same symbol ( YListNode ) is used for the struct name (or struct tag) and the typedef of the struct. This is a problem for two reasons:

  • The first is ambiguity. Maintaining the code in the future will require extra attention for coders to apply this multiply defined symbol correctly.

  • The second, which addresses your specific question, is that until the struct typedef (YListNode) is defined, it should not be used in the definition of any member of that struct.

This configuration in a CLANG compiler results in this error: 9, 5 error: must use 'struct' tag to refer to type 'YListNode'

To address the issue:
Either choose different symbols for these struct components. For example:

typedef struct yNode {
    int Yval;
    struct yNode *next;
}YListNode;

And apply the same to the other declarations as well.

Or use the following forward declarations placed prior to the struct definition statements:

typedef struct YListNode YListNode;
typedef struct YList YList;
typedef struct XListNode XListNode;
typedef struct List List;
ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Are you sure ? we can use the same symbol. Infact, it likes : `typedef struct YListNode YListNode;` – Hitokiri Apr 09 '20 at 12:57
  • @Hitokiri is right, this is absolutely legal, and very used in fact. You said not very well, in fact *YListNode* is known as *typedef struct ..* **after** the *struct* definition, so too late for _YListNode *next_ – bruno Apr 09 '20 at 13:02
  • @Hitokiri - Yes, for the shown configuration it is an error. In the original post the question was specifically asking _why_ for the shown declarations was the error occurring. Your suggestion about using forward declaration is another way to do it. – ryyker Apr 09 '20 at 13:03
  • @bruno - agree with your assessment that it is not worded well, I borrowed from my compilers vernacular. – ryyker Apr 09 '20 at 13:05
  • @bruno - When I run OP code precisely as it is provided, I get the following error for each `struct` declaration: "error: must use 'struct' tag to refer to type 'YListNode'" – ryyker Apr 09 '20 at 13:09
  • @ryyker, yes because when defining *next* the type *YListNode* (alone) is still unknown, and a solution is to do _struct YListNode * next_, in fact the compiler give a way to fix, the compilers do more and more with the time, the work they do is awesome – bruno Apr 09 '20 at 13:11
  • @bruno, i know it's absolutely legal (i use like that in my code). I just want to say we can use the same symbol. – Hitokiri Apr 09 '20 at 13:16
  • @Hitokiri yes,, the remark I did with your name was for ryyker. I know you know this is legal, and yes it is more simple to use the same symbol – bruno Apr 09 '20 at 13:18
  • @ryyker in this question, we can use forward declaration. In another way, we can just add `struct` before the `YListNode` – Hitokiri Apr 09 '20 at 13:18
  • @ryyker and bruno, you can test with this declaration typedef struct YListNode { int Yval; struct YListNode *next; }YListNode; It 's not false – Hitokiri Apr 09 '20 at 13:20
  • Let remark that problem does not exist in C++, when you reach the { in *struct XX {* it is possible to use XX because it is known. Thanks to that it is also useless to have the *typedef*, the struct definition is enough – bruno Apr 09 '20 at 13:20
  • @Hitokiri - _i know it's absolutely legal (i use like that in my code)._ what compiler are you using? And, are you saying that without forward declarations that the struct definitions as shown in OP are absolutely legal? (I will accept that if your statement is meant to say _with forward declarations..._.) – ryyker Apr 09 '20 at 13:28
  • @ryyker i know it's absolutely legal, (i use like that in my code). It means i declared as your answer. I use GCC, and with GCC, we can use the same symbol. Sorry for my english if it makes you confuse – Hitokiri Apr 09 '20 at 13:33
  • 1
    @Hitokiri - Your english is fine :) `GCC` is a great compiler, and I use it all the time for certain types of projects, however, [depending on how the compiler settings are configured](https://stackoverflow.com/q/2855121/645128) it will not always be strictly compliant. The link discusses this topic at length. Lately I have been using the CLANG compiler, and is the one I used to come to my current conclusions. I do not argue that you are seeing what you have commented, but I believe the link may explain why we see different results. – ryyker Apr 09 '20 at 13:38
1

You can use the forward declaration to first declare the typedef struct, and then you define them.

Here it is:

    /* forward declaration */
    typedef struct YListNode YListNode;
    typedef struct YList YList;
    typedef struct XListNode XListNode;
    typedef struct List List;

    typedef struct YListNode {
        int Yval;
        YListNode *next;
    }YListNode;

    typedef struct YList {
        YListNode *head;
        YListNode *tail;
    }YList;

    typedef struct XListNode {
        XListNode * prev;
        int Xval;
        YList yList;
        XListNode *next;
    }XListNode;

    typedef struct List {
        XListNode *head;
        XListNode *tail;
    }List;
campescassiano
  • 809
  • 5
  • 18
  • I think you can be more clear, you give how to solve but not why there is a problem ;-) – bruno Apr 09 '20 at 13:06