mdh said:
A quick ?

question about Typedefs.
There is a very brief discussion about this in K&R ( p146). Googling
this group, there is a surprising dearth of questions about these.
From one of the threads, there is sound advice ( to me at any rate)
not to hide pointers behind typedefs.
So, may I ask the group when the use of typedefs really makes sense?
Sorry if this is somewhat general, but there are no exercises ( not
that I am asking for any!!) provided.
A typedef creates an alias (a name consisting of a single identifer)
for an existing type.
Strictly speaking, typedefs are almost never necessary. (The one
exception, I think, involves the va_arg macro for variadic functions,
which requires a type name that can be used in a certain way.)
It's very common to create a typedef for a struct type. In my opinion
(which plenty of smart programmers don't share), this is poor style.
For example, given:
struct foo {
/* member declarations */
};
the type already has a perfectly good name, "struct foo". Why create
another one? The counterargument is that it's more convenient to have
a simple single-identifier name for the type.
The syntax for function types and pointer-to-function types is
sufficiently convoluted that it can be worthwhile to simplify it by
using typedefs. For example if you want a pointer to a function that
takes a double argument and returns a double result, you can write:
double (*ptr)(double);
or you can write:
typedef double math_func(double);
math_func *ptr;
Or, if you prefer, you can write:
typedef double (*math_func_ptr)(double);
Hiding pointerness behind a typedef is usually a bad idea, but in the
case of a pointer-to-function type it's more defensible.
A typedef is also appropriate when you want an abstract data type,
where code that uses the type shouldn't know anything about its
internals. The type FILE, declared in <stdio.h> is a good example.
(The use of all-caps isn't particularly consistent with modern style,
which uses all-caps for macros, but it's been around for a very long
time.)
And typedefs are often appropriate for numeric types. I *don't* mean
something like
typedef unsigned int uint;
which does nothing but save you a little typing. I'm referring to a
weaker form of data abstraction, where code that uses the typedef
knows that it's an integer type, and whether it's signed or unsigned,
but doesn't need to know *which* predefined type because it can vary
from one system to another.
To summarize:
Use a typedef when the internal characteristics of the type are
irrelevant to code that uses it (e.g., FILE).
Use a typedef when a named type can be implemented differently on
different systems (e.g., int32_t, size_t).
Use a typedef to give a name to something that can otherwise only be
referred to by some complicated syntax, particularly in the case of
function types and pointer-to-function types.
If you're using a typedef just to save a few keystrokes, don't bother.
Given "typedef unsigned int uint;", uint can never be anything other
than unsigned int; just use its real name, "unsigned int". And if
uint *can* be something other than unsigned int, "uint" is a lousy
name.
Don't bother with typedefs for struct types unless you're doing the
kind of data abstraction I discussed above -- but reasonable people
differ on this.
And I can think of at least one exception to the above. I don't mind
typedef unsigned char byte;
"byte" can never be anything other than unsigned char, but assigning
the name "byte" can make the usage clearer (i.e., this is raw data,
not necessarily characters).