User defined types, structures and unions
Sometimes, the basic set of data types defined in the C language such as
int, float etc. may be
insufficient for your application. In circumstances such as these,
you can create your own data
types which are based on the standard ones. There are three mechanisms
for doing this in C:
The typedef keyword.
The typedef keyword allows the programmer to create new data types :- in
a way.
You typically use the typedef keyword to improve the readability of
your code and as a means
of abbreviating it.
For example,
the statement
typedef unsigned char byte;
creates a new datatype called byte which is short-hand for unsigned
char. You can the use
this new type to declare variables as follows:
byte a;
Structures
Structures are aggregate data types. For example, you can create
a structure which contains
an integer, a float and a string. This grouping of data types
into a single structure may have
particular meaning to your application. For example, a banking
application will require some
form of customer record which will probably consist of an account number,
name, address,
balance and presumably other additional items. It seems logical
to store these different items
in such a way that they are accessible as a unit or using a single
reference. The struct keyword
allows us to design such a collection of data items. A
banking customer record structure could
be defined as follows:
struct Customer_Record
{
char CustomerName[50]; /* Customer name of up
to 50 characters */
char AccountNumber[11]; /* 10 digit Account
number */
float Balance;
char Address[1024]; /* Include 1k for storage
of the customer address.
}
The above merely defines a new structure type. To actually
declare (create space for) a particular
customer record you could enter the following:
struct Customer_Record MyRecord; /* declare a
structure called MyRecord of struct type Customer_Record */
The way the variable MyRecord occupies memory may be thougth of as shown
in the following diagram
Now, it seems a bit cumbersome to have to keep including the struct
keyword everytime we want to declare a
variable of this type. To shorten the declaration we could use
the typedef keyword as follows:
typedef struct Customer_Record_Tag
{
char CustomerName[50]; /* Customer name of up
to 50 characters */
char AccountNumber[11]; /* 10 digit Account
number */
float Balance;
char Address[1024]; /* Include 1k for storage
of the customer address.
} Customer_Record;
and we can then declare a customer record variable as follows:
Customer_Record MyRecord;
Note: the symbol Customer_Record_Tag is unused.
You access the individual members of a structure using the dot (.) operator.
For example
MyRecord.Balance = 1000000; /* wishful thinking */
Unions
Unions allow you to create variables which share a common memory space.
Unions are
a bit like structures, in that they appear to be an aggregate data
type. However, the main difference
is that the union members occupy overlapping memory areas. Why
would you create such a strange
variable? Well, there are several instances in which this could
be useful. For example, you might
want 2 different ways of interpreting a given piece of data.
One "view" of this piece of data might be
as a stream of 16 bit integers, another might be as a stream of 8 bit
bytes. Don't be fooled into thinking
that unions can help you to preform automatic type conversions
from say floats to strings and so on. They
can only allow you to interpret a given collection of bytes in memory
in a number of different ways. Personal
experience has shown me that unions are best avoided if at all posisble
as they are confusing and their behaviour
can depend on the operating system/hardware platform. In certain
circumstances (which usually related
to hardware interfacing) I have found them to be useful but these were
rare circumstances indeed. The
following example shows how space is assigned to a union in a system
which has a 16 bit integer length.
union SomeUnion {
int i;
char str[4];
}
The memory for unions of this type is assigned as follows: