enum
is a way of creating a user-defined integral type which
can be assigned a limited number of constant values
enum enum-name {
const-list} variable-name;
enum shapetype
and associate three constant values
(circle
, triangle
,
square
) with it:
{ enum shapetype {circle, triangle, square} s1, s2; s1 = circle; s2 = s1 + 1; if (s2 != triangle) return 0; return 1; }
enum name
is usually just an alias for
int
and the enumerated values are just aliases for integral constants
(in the enum shapetype
above,
triangle == 0
,
circle == 1
and
square == 2
)
enum wierdtype {first = 5, min = first, second, third, fourth = 28, fifth = fourth - 6, sixth, seventh = 1, max = seventh};is almost the same as
#define first 5 #define min 5 #define second 6 #define third 7 #define fourth 28 #define fifth 22 #define sixth 23 #define seventh 1 #define max 1
enum
variable
is not strictly limited to the values associated with that
enum
and an enumerated value may be assigned to variables other
than those declared with the enum
associated with that enumerated value
{ enum dwarf {happy, sleepy, sneezy, dopey, doc, grumpy, bashful} d; enum {anonymous, unnamed, hidden}; int i; enum dwarf x; d = 17; i = happy; x = hidden; }are all legal, though they may cause the compiler to issue a warning
enum name
is merely
a suggestion that an "int
-like" variable use the associated
constants; the compiler does nothing to enforce it or to restrict the values
to those specified by the enum
enum vowel {a, e, i, o, u};
, you cannot
use i
as a variable name later
enum
instead of const int
?
const int
as a variable, meaning
its value must be fetched from memory before being used
enum
values are usually treated just like integral constants
and are thus immediately accessible
enum
instead of #define
?
#define
d values are replaced with integral constants
by the preprocessor, so the compiler never sees them
enum
values are handled by the compiler and thus can have
entries in the symbol table which could be used by a debugger
struct
is a way of encapsulating a group of related values
in a single object
{ struct timestamp { int hour; int minute; int second; } t; t.hour = 9; t.minute = 45; t.second = 32; }
->
operator may be used to access the members of a
structure via a pointer:
{ struct timestamp *tp = &t; tp->hour += 1; tp->second = 0; }
{ struct timestamp t2 = { 12, 0, 0 }; struct datestamp { int year; char month[4]; int day; } d = { 1996, "Jan", 24 }; }
{ struct stamp { struct timestamp ts; struct datestamp ds; } dt = { { 1, 2, 3 }, { 1492, "Feb", 28 } }; dt.ts.hour = dt.ts.minute = dt.ts.second = 0; dt.ds.year = 1776; dt.ds.day = 4; }
struct list { int ival; double dval; struct list *next; };
struct small { char c1, c2, c3; int i1, i2, i3; }; struct big { char c1; int i1; char c2; int i2; char c3; int i3; };
struct smaller { unsigned sevenbits : 7; unsigned fourvals : 2; } s;creates a structure with two members:
sevenbits
which
can hold values between 0 (binary 0000000) and 127 (binary 1111111),
and fourvals
which can hold values between 0 (binary 00)
and 3 (binary 11)
s.sevenbits = 32; s.fourvals /= 2;
signed
or unsigned
(though pre-ANSI compilers may only allow unsigned
)
struct holey { unsigned sea : 3; unsigned : 3; unsigned see : 3; };
&
operator cannot be applied to a bitfield,
since a bitfield is only a subset of the bits in a word and thus
has no address
union
is a way of defining two or more variables
which share the same memory:
union manytypes { char c; int i; double d; unsigned *up; } u;
u.i
and then assigning a value to u.c
will cause some part of
the value of u.i
to be overwritten
union
s to manipulate datatypes
behind the compiler's back will void your warantee
union
look just like struct
references (though the effect is totally different):
{ union manytypes mt, *mtp; mtp = &mt; mt.d = 1.2345; mtp->i = 3; }sets
mt.d
to 1.2345
, then sets mt.i
to 3
(which destroys the mt.d
value, since the
two share the same memory)
typedef
is used to create an alias for another type:
typedef char *string;creates a keyword named
string
which can be used as
an alias for "pointer to character":
string str; char *cp;both create pointers to
char
typedef
is a bit more flexible than #define
because, since typedef
is handled by the compiler, more
complex types can be handled with typedef
than could be dealt
with by the textual manipulations available to the preprocessor
typedef int (*CmpFunc)(const char *, const char *); CmpFunc strcmp, numcmp;using only the preprocessor