1

GCC gives me an "array type has incomplete element type"-error message when i try to compile this:

typedef struct _node node;
struct _node{
 int foo;
 node (*children)[2];
 int bar;
};

In memory the struct should look like this

0x345345000000 foo
0x345345000004 pointer to 1. child node
0x345345000008 pointer to 2. child node
0x34534500000C bar

2 Answers 2

7

That's because the C type expression works the other way round.

This:

node (*children)[2];

reads as the following: the contents of children, when dereferenced (* is applied to them), yield something on which the array operator [] can be applied, yielding a node. Which means that children is a pointer to an array of two node. However, you do not want a pointer to an array, you want an array of two pointers. For that, you should put the parentheses thus:

node *(children[2]);

which then reads as: the contents of children are an array of two values; applying * on one of them yields a node. This is what you want: an array of two pointers to node. Note that this is equivalent to:

node *children[2];

because in the C syntax, when it comes to type expressions, the [] operator takes precedence over the * operator.

In your initial version, the C compiler grumbles because at the time it reads the declaration, it does not know what size node is (the structure definition is not complete yet), and, as such, has trouble imagining a type "array of two node". This is a rather indirect symptom of the problem.

Side note: you should refrain from using _node or any other identifier beginning with an underscore in your code. These identifiers are reserved for "the implementation". In practice, system headers may use them, and collisions could prove harmful. Personally, I tend to add the underscore at the end, like this: typedef struct node_ node;

Sign up to request clarification or add additional context in comments.

3 Comments

I'm confused why you'd use an underscore at all. typedef struct node node; is perfectly valid and makes it possible to use struct node if you ever want/need to.
@R..: I have encountered old C compilers where typedef struct node node; was not accepted. Also, in C++ (not C), the namespaces for structure tags and type names are not fully disjoint; so I took the habit to use distinct identifiers for structure tags and type names, hence the final underscore. I find that it also helps my brain: it makes it more obvious, to my aging neurons, whether a given identifier is a structure tag or a typedef-ed name.
I'm guessing those compilers also lack void pointers. As for C++, a struct automatically creates a type, but redundant typedefs are permitted by the language, with typedef struct foo foo; as a special case that's very useful.
2

Instead of this:

 node (*children)[2];

Use this:

 struct _node* children[2];

2 Comments

If I replace "node" by "struct _node" in line 4 it doesn't work. Is that what you mean?
Actually its "node* children[2];", but thank you. It worked when I removed the brackets. ... Damn pointers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.