Pointer to self struct in C

2019-07-29 15:52发布

Given the following code:

typedef struct elementT {
  int data;
  struct elementT *next;
} element;

Why is it necessary to do struct elementT *next and I can't do element *next inside the struct declaration itself? Is it because it is not declared yet?

标签: c struct typedef
4条回答
虎瘦雄心在
2楼-- · 2019-07-29 16:04

The typedef only takes place after the struct has been defined. Consider the following code; the syntax is invalid, but it hopes it shows the order/precedence of things:

typedef (struct {
  int field1, field2;
}) item;

I.e., the struct{...} is an "expression" that denotes a type. The typedef operates on that type by giving it a name.

By contrast,

struct foo {
    foo *next;
};

works because of two special rules of C: struct <name> not only defines a type, but gives it a struct tag as well, and that tag is immediately visible inside the rest of the struct declaration (for the obvious reason: linked lists, trees, etc. would be very painful to implement without these rules).

查看更多
狗以群分
3楼-- · 2019-07-29 16:05

Because C said so:

(C99, 6.2.1p7) "[...] Any other identifier has scope that begins just after the completion of its declarator."

查看更多
ゆ 、 Hurt°
4楼-- · 2019-07-29 16:27

The name elementT, part of the type name struct elementT, becomes visible (as an incomplete type) as soon as the compiler sees the two tokens struct elementT, so you can use it as a type name inside the struct definition.

The name element, which is a typedef name, doesn't become visible until the identifier element appears, which is after the end (the closing }) of the struct definition; thus you can't use it inside the struct definition, simply because it doesn't exist yet.

My own personal preference (and plenty of very smart people differ with me on this point) is not to use typedef at all. The type already has a perfectly good name, struct ElementT; why add a second one? I'd just write:

struct element {
    int data;
    struct element *next;
};

and refer to the type as struct element.

If you feel that having a single-word name for the type is sufficiently useful, of course, you can still use the typedef. Just remember that the typedef name won't be visible until after the end of the declaration. And there's no need to use two different identifiers:

typedef struct element {
    int data;
    struct element *next;
} element;

Now you can refer to the type either as struct element or as element.

(Note that C++ has different rules; it effectively creates an implicit typedef for a struct (or union, class, or enum) type. In C++, the typedef is unnecessary but harmless.)

查看更多
地球回转人心会变
5楼-- · 2019-07-29 16:28

You can achieve this behaviour if you separate the struct declaration from its definition:

struct ElementT;                   // not strictly needed

typedef struct ElementT element;   // this declares "struct ElementT" as well

struct ElementT
{
    element * next;
};
查看更多
登录 后发表回答