61

How can I have a pointer to the next struct in the definition of this struct:

typedef struct A {
  int a;
  int b;
  A*  next;
} A;

this is how I first wrote it but it does not work.

Jens
  • 69,818
  • 15
  • 125
  • 179
claf
  • 9,043
  • 17
  • 62
  • 79
  • Note C11 [§6.7.2.1 Structure and union specifiers ¶3](https://port70.net/~nsz/c/c11/n1570.html#6.7.2.1p3): _A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), …_ – Jonathan Leffler Nov 14 '19 at 06:34

6 Answers6

85

You can define the typedef and forward declare the struct first in one statement, and then define the struct in a subsequent definition.

typedef struct A A;

struct A
{
    int a;
    int b;
    A* next;
};

Edit: As others have mentioned, without the forward declaration the struct name is still valid inside the struct definition (i.e. you can used struct A), but the typedef is not available until after the typedef definition is complete (so using just A wouldn't be valid). This may not matter too much with just one pointer member, but if you have a complex data structure with lots of self-type pointers, may be less wieldy.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    This is the "canonical" way of doing this. – unwind Feb 03 '09 at 08:50
  • 14
    unwind: many coding style conventions for C vehemently oppose typedefing structs. I wouldn't say it's canonical at all. – Chris Young Feb 03 '09 at 10:40
  • 2
    If I could vote up comments, Chris Young would get a +1. There is a huge difference between native types and aggregate structures. **Don't** hide it behind a typedef. – ephemient Feb 03 '09 at 21:37
  • @ephemient: You can now. – Keith Thompson May 28 '14 at 15:55
  • 3
    @ephemient Why should I not hide it? They're just implementation details. – YoTengoUnLCD Feb 26 '17 at 06:02
  • Why are there two 'A's in typedef struct A A; ? – turner Nov 30 '17 at 23:23
  • 1
    @turner: because one `A` identifies the structure type in `struct A`, and the second gives the type a name (alias) of `A`. If you had `typedef int B;`, then `int` is the type and `B` is the new name for the type. In the same way, with `typedef struct A A;`, then `struct A` is the type and `A` is the new name for the type. – Jonathan Leffler Nov 14 '19 at 06:37
68

In addition to the first answer, without a typedef and forward declaration, this should be fine too.

struct A 
{ 
    int a; 
    int b; 
    struct A *next; 
};
Chris Young
  • 15,627
  • 7
  • 36
  • 42
21

You are missing the struct before the A*

  typedef struct A {
    int a;
    int b;
    struct A* next;
  } A;
Miles D
  • 7,960
  • 5
  • 34
  • 35
14

You can go without forward declaration:

struct A {
    int a;
    int b;
    struct A *next;
};
qrdl
  • 34,062
  • 14
  • 56
  • 86
9

Please, you're in C, not C++.

If you really must typedef a struct (and most programmers that I work with would not¹), do this:

typedef struct _A {
    int a;
    int b;
    struct _A *next;
} A;

to clearly differentiate between _A (in the struct namespace) and A (in the type namespace).

¹typedef hides the size and storage of the type it points to ― the argument (and I agree) is that in a low-level language like C, trying to hide anything is harmful and counterproductive. Get used to typing struct A whenever you mean struct A.

ephemient
  • 198,619
  • 38
  • 280
  • 391
  • 2
    How does "struct A" tell me anything about its size? – quant_dev Feb 03 '09 at 23:25
  • It tells you that it's an aggregate structure, and thus many things like passing it as arguments, returning it, comparisons, and `a = b` are inefficient or will not work. – ephemient Feb 04 '09 at 01:08
  • 4
    _A is a reserved name. A_ would be fine. – MSalters Feb 12 '09 at 10:31
  • 2
    Nitpick: _A is a bad name: leading underscores belong to the compiler. [edit] Damn, I think I just echoed MSalters. – Bernd Jendrissek Jun 18 '10 at 14:07
  • 2
    I have never, in all my time programming, encountered a problem from giving the struct and the typedef the same name, and then I only bother giving the struct a name in this exact case (linked lists etc). I think you are just promoting FUD. Can you give an example where it causes problems to give the same name for both? Also I have never encountered any issue by using typedef on all my structs whatsoever, so I find your argument that it is 'harmful and counterproductive' to be a bit over the top. – Wayne Uroda Jun 21 '18 at 02:53
  • Note that the `_A` in `struct _A` is in the 'tag' name space; the `A` at the end of the `typedef` is in the 'ordinary identifiers' name space (shared with variable names, function names, type names, etc). To the extent there is a structure name space, it means the set of structure member names (and each structure or union type has its own name space). See C11 [§6.2.3 Name spaces of identifiers](http://port70.net/~nsz/c/c11/n1570.html#6.2.3). – Jonathan Leffler Oct 13 '18 at 00:25
  • Note that you should not, in general, create function, variable, tag or macro names that start with an underscore. Part of [C11 §7.1.3 Reserved identifiers](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) says: — _All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use._ — _All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces._ See also [What does double underscore (`__const`) mean in C?](https://stackoverflow.com/a/1449301) – Jonathan Leffler Oct 13 '18 at 00:26
0
typedef struct {
 values
} NAME;

This is shorter way to typedef a struct i think its the easiest notation, just don't put the name infront but behind.

you can then call it like

NAME n;  

NAME *n; // if you'd like a ptr to it.

Anything wrong with this approach?

user7296055
  • 105
  • 3
  • 2
    well as stated in the question, the need is to have a pointer INSIDE the struct (chained list) so I don't see what your answer add here. – claf Jan 10 '17 at 16:08