Name | Description | Notes | Source | Availability | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|
typedef |
Declare type alias | L | S | Keyword | C89 | C90 | C95 | C99 | C11 |
C permits the definition of type aliases,
alternative names for existing types, using the keyword typedef
. For
example:
typedef int counter_type;
This defines a new type name counter_type
which is an alias for int
. Now
variables, types and functions an be
declared with this type:
struct entry { char name[20]; counter_type score; }; counter_type num_of_entries; void list_entries(struct entry *base, counter_type howmany);
Such declarations are equivalent to the following, with
counter_type
replaced with
int
:
struct entry { char name[20]; int score; }; int num_of_entries; void list_entries(struct entry *base, int howmany);
typedef
isn't merely doing textual substitution. If we define
counter_type
with something more
syntactically complex:
typedef int counter_type[100];
…the equivalent declarations become:
struct entry { char name[20]; int score[100]; }; int num_of_entries; void list_entries(struct entry *base, int howmany[100]);
Note that the typedef
construct is syntactically a variable declaration. If you
take an existing variable declaration:
struct wedge my_var[100];
…and put typedef
in
front of it:
typedef struct wedge my_var[100];
…the declared name my_var
no longer
identifies a variable, but becomes a type alias for whatever
type my_var
would have been without
the typedef
.
A type alias can be useful for hiding the internal details
of a type, making it easier to change those details under
different circumstances. This is used throughout the standard
library to mask platform-specific variation. For example,
size_t
is specified to be an
alias for an unsigned integer type. This allows it to be (say)
unsigned
on one
platform, while being unsigned long
on
another, according to the requirements and capabilities of
the platform.
A type alias can also be useful for self-documenting code.
Again, this utility is employed in the standard library in
the specification of rsize_t
, which is an alias
for size_t
. It is documented that
functions that take rsize_t
as parameters
perform certain run-time constraint checking on those
arguments, and fail in a graceful and detectable way.
A further use for type aliases is to simplify complex
declarations. The declaration for the function signal
is unintuitive:
void (*signal(int s, void (*handler)(int)))(int);
The declaration is complicated by the fact that it returns a pointer to a function, and that one of its parameters is of the same type. We can simplify the declaration by using an alias for this pointer-to-function type:
typedef void (*signal_handler_t)(int); signal_handler_t signal(int s, signal_handler_t handler);
Alternatively, we could expose the fact that a pointer is required and returned by excluding it from the alias:
typedef void signal_handler_t(int); signal_handler_t *signal(int s, signal_handler_t *handler);
Note that, in this case, the typedef
is
syntactically equivalent to a function prototype.