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?
#defined 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
unions 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