Reputation: 1304
I have a C template which is given me as homework. But before doing homework, I need to understand the usage of "typedef" and "struct" clearly to move on coding. Here is the code;
typedef struct NODE_s *NODE;
typedef struct NODE_s
{
NODE right;
NODE left;
unsigned long data;
int height;
} NODE_t[1];
typedef struct TREE_s *TREE;
typedef struct TREE_s
{
NODE root;
} TREE_t[1];
TREE tree_init();
NODE node_init(unsigned long data);
First of all, what is the line typedef struct NODE_s *NODE;
is doing here? Why it is named like a pointer with a *
?
Then, after the struct definition, what is the purpose of creating a variable named NODE_t[1]
, is the square brackets with the number "1" something connected with an array, or it is just something else?
Lastly, when the tree_init();
and node_init(unsigned long data);
functions are declared, why the TREE and NODE datatype names are used to the contrary they were declared as *TREE
and *NODE
before the struct definitions? Thank you for the answers.
Upvotes: 1
Views: 672
Reputation: 755074
The template you were given is this, where I've added numbers to some of the lines for ease of reference:
typedef struct NODE_s *NODE; // 1
typedef struct NODE_s // 2
{
NODE right; // 3
NODE left;
unsigned long data;
int height;
} NODE_t[1]; // 4
typedef struct TREE_s *TREE;
typedef struct TREE_s
{
NODE root;
} TREE_t[1];
TREE tree_init(); // 5
NODE node_init(unsigned long data);
What are the problems here?
NODE_s
; (2) the name NODE
is a synonym for struct NODE_s *
. The structure type is incomplete at the moment; no details are known about its members.typedef
, but also starts the definition of the type struct NODE_s
(because of the {
that follows on the next line).NODE
is already known; it can be used here. It means the same as if you wrote struct NODE_s *right;
.NODE_t
is an alias for the type struct NODE_s[1]
, an array of 1 struct NODE_s
. It isn't clear what this is going to be used for. I have reservations (at best) about its existence. (You can also apply the discussion in points 1, 2, 4 to the struct TREE_s
type, mutatis mutandis.)tree_init()
function can be called with any number of arguments of any type because no information is specified about the number or type of those arguments. We do know it is not a variadic function (variable argument list, like printf()
) because those must have a full prototype declaration ending with , ...)
in scope before they're used. If you want to specify that the function takes no arguments, say so: TREE tree_init(void);
.I think the intent behind the NODE_t
and TREE_t
types is to allow you to write, for example:
int main(void)
{
TREE_t x = { 0 };
if (x->root != 0)
return 1;
return 0;
}
I'm not convinced whether that's sufficiently helpful to warrant the type compared with using struct NODE_s x
and using x.root
in the test. It does save you from having to add an &
when passing a pointer to a function; again, I'm not sure it is really sufficiently helpful to warrant its existence.
What I would prefer to see as the template is:
typedef struct NODE_s NODE;
struct NODE_s
{
NODE *right;
NODE *left;
unsigned long data;
int height;
};
typedef struct TREE_s TREE;
struct TREE_s
{
NODE *root;
};
extern TREE *tree_init(void);
extern NODE *node_init(unsigned long data);
This removes the pointers from the typedef
statements, avoids the somewhat peculiar array types, and uses an explicit prototype for tree_init()
. I personally prefer to have function declarations marked with extern
; in a header, they'll match the extern
on those rare global variables that are declared in the header. Many people prefer not to use extern
because the compiler assumes that anyway — so be it; the most important thing is consistency.
The code in main()
would now be written:
int main(void)
{
TREE x = { 0 };
if (x.root != 0)
return 1;
return 0;
}
The difference? An arrow ->
changed to a dot .
. Not a lot of problem there. However, when calling functions, you'd probably use &x
whereas with the TREE_t
type, you would just write x
(because it's an array).
Upvotes: 4