question about struct??

C

Chris Torek

I think it needs to be emphasised how a typedef tells the compiler that
[this] is a new type ...

It is not the "typedef" keyword that defines the type. It
is the "struct {" pair that does it:
typedef struct {int a; int b;} st;

This means:

1) "typedef" -- set the "typedef flag", so that declarations
of variable are modified.

2) "struct {" -- begin defining a new type, which has no tag
(the compiler just has to make one up, internally).

3) "int a; int b; }" -- the contents of the new type.

4) "st" -- declare a variable, "st" is a variable of type
"struct <magic_compiler_name_00001>", oops wait the
typedef flag is set so make "st" an alias for that type
rather than a variable of that type.

5) ";" -- finish it all off; reset the typedef-flag.

Note that if we write, instead:

struct S { int a; int b; };
typedef struct S st, q, abc, *def, ghi[4];

we will first define a new type (struct S), then define three
aliases for struct S ("st", "q", and "abc"), one alias for a pointer
to that struct S ("def"), and one alias for an array of size 4 of
struct S. We can then do:

void f(struct S arg) {
q local = arg;
def x = &q;

return *x;
}

There is only one underlying user-defined type here, "struct S".
There are lots of aliases for it, but it is the "struct <tag> {"
that created it.

Note also that if you intend to make self-referential or
mutually-referential structures, tags are *absolutely required*:

struct list {
struct list *l_next;
int l_whatever;
/* ... more stuff ... */
};

There is no way to avoid the "struct <tag>" here. You *can* do
this:

typedef struct list list;
struct list {
list *l_next;
int l_whatever;
...
};

but the tag is absolutely, completely, 100% necessary.

Since tags are *sometimes* required, and "typedef" in this
case merely saves keystrokes, I recommend always using tags
and never bothering with the typedefs. There are some valid
"pro-typedef" arguments (which I will not repeat here), but
learning "struct <tag>" is necessary, and using the tag is
never harmful. Might as well Just Do It, as the ads say.

(Note that there is exactly one situation in C where typedef
is in fact *required*, having to do with the va_arg() macro
in <stdlib.h>. The second parameter to va_arg is a type-name,
and it must be one that can be turned into "pointer to <type>"
by adding an asterisk at the end, as by macro expansion. For
most C types, this happens naturally:

int i = va_arg(ap, int); /* int * => pointer to int */
char *cp = va_arg(ap, char *); /* char ** => pointer to (char *) */

but there are a few where it does not:

void (*fp)(int) = va_arg(ap, ???what can you put here???);

The variable "fp" has type "void (*)(int)", or "pointer to
function taking int and returning void". A pointer to that
type is a "pointer to pointer to function taking int and
returning void", which is spelled "void (**)(int)" in C. In
other words, the extra "*" has to go in the middle, not at
the end. So you must insert a typedef, such as:

typedef void (*zorg_function_ptr)(int);
zorg_function_ptr fp = va_arg(ap, zorg_function_ptr);

or:

typedef void zorg_function(int);
zorg_function *fp = va_arg(ap, zorg_function *);

Either of these is valid. When dealing with complicated
function-pointer types, using typedef can make the code more
readable, too. But I find that typedef "damages" C syntax rather
badly, in that what used to be simple and obvious becomes complex
and unobvious:

typedef int x;
int f() { x x; x = 42; return x; }

This is valid C code! There are situations worse than this, in
which it is not at all clear whether some identifier is a typedef-name
or an ordinary identifier; only some entity that has access to the
entire C code, and has parsed it token by token, can tell. C
compilers can figure it out; but human programmers get it wrong.
If you just spell out the "struct" keyword, it becomes simple
and obvious again, and programmers can get it right again.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top