|
|
The declaration for a constant follows this form:
const name-identifier = n;const is used to define a symbolic name for a constant; it does not declare any data. The symbolic constant may be used anywhere a regular constant may be used.
The following example defines a symbolic constant DOZEN, equal to 12.
const DOZEN = 12;
typedef does not declare any data either, but serves to define new identifiers for declaring data. The syntax is:
typedef declaration;The new type name is actually the variable name in the declaration part of the typedef.
The following example defines a new type called eggbox using an existing type called egg and the symbolic constant DOZEN:
typedef egg eggbox[DOZEN];Variables declared using the new type name have the same type as the new type name would have in the typedef, if it was considered a variable. For example, the following two declarations are equivalent in declaring the variable fresheggs:
eggbox fresheggs; egg fresheggs[DOZEN];When a typedef involves a
struct
,
enum
,
or
union
definition, there is another (preferred) syntax that may be used to
define the same type.
In general, a
typedef
of the following form:
typedef <<struct, union, or enum definition>> identifier;may be converted to the alternative form by removing the typedef part and placing the identifier after the
struct
,
enum
,
or
union
keyword, instead of at the end.
For example, here are the two
ways to define the type
bool
:
typedef enum { /* using typedef */ FALSE = 0, TRUE = 1 } bool;This syntax is preferred because one does not have to go to the end of a declaration to learn the name of the new type.enum bool { /* preferred alternative */ FALSE = 0, TRUE = 1 };
Optional-data is a form of
union
.
Because it occurs frequently, it has been given its own declaration
syntax.
It is declared as follows:
type-name *identifier;This is equivalent to the following
union
:
union switch (bool opted) { case TRUE: type-name element; case FALSE: void; } identifier;It is also equivalent to the following variable-length array declaration, because the boolean opted can be interpreted as the length of the array:
type-name identifier<1>;Optional-data is useful for describing recursive data-structures such as linked-lists and trees. For example, the following defines a type stringlist that encodes lists of arbitrary length strings:
struct *stringlist { string item<>; stringlist next; };It could have been equivalently declared as the following union:
union stringlist switch (bool opted) { case TRUE: struct { string item<>; stringlist next; } element; case FALSE: void; };or as a variable-length array:
struct stringlist<1> { string item<>; stringlist next; };Both of these declarations obscure the intention of the stringlist type, so the optional-data declaration is preferred over both of them. The optional-data type also has a close correlation to how recursive data structures are represented in high-level languages such as Pascal or C by use of pointers. The syntax is the same as that of the C language for pointers.