C Programming: Struct, Typedef, Union
C Programming: Struct, Typedef, Union
& UNION
In this session we will learn struct and union types,
typedef and enum
www.tenouk.com,
1/93
With array, we can only declare one data type per array.
For different data type, we need another array
declaration.
It is single type aggregate data type.
Struct overcomes this problem by declaring composite
data types which can consist different types.
A structure is a collection of related data items stored in
one place and can be referenced by more than one
names.
These data items are different basic data types. So, the
number of bytes required to store them may also vary.
A structure type is a user-defined composite type.
It is composed of fields or members which can be
different types.
www.tenouk.com,
2/93
3/93
tag
struct student {
char chIdNum[5];
char chName[10];
char chGender;
int nAge;
};
www.tenouk.com,
4/93
5/93
www.tenouk.com,
6/93
www.tenouk.com,
7/93
8/93
www.tenouk.com,
10/93
11/93
www.tenouk.com,
12/93
www.tenouk.com,
13/93
14/93
15/93
A bit field declaration may not use either of the type qualifiers,
const or volatile.
The following structure example has four bit-field members
left, right, front and rear, occupying 4, 3, 4 and 5 bits
respectively,
struct direction { // declare direction bit field
int left : 4;
// 00000000 0000XXXX
int right : 3;
// 00000000 0XXX0000
int front : 4;
// 00000XXX X0000000
int rear : 5;
// XXXXX000 00000000
};
16/93
www.tenouk.com,
17/93
If a series of bit fields does not add up to the size of an int, padding
can take place.
The amount of padding is determined by the alignment
characteristics of the members of the structure.
The following example demonstrates padding.
Suppose that an int occupies 4 bytes (4 x 8 = 32 bits). The example
declares the identifier onoffpower to be of type struct
switching,
struct switching {
unsigned light : 1;
unsigned fridge : 1;
int count;
unsigned stove : 4;
unsigned : 4;
unsigned radio : 1;
unsigned : 0;
unsigned flag : 1;
} onoffpower ;
www.tenouk.com,
/* 4 bytes */
18/93
Member Name
light
fridge
(padding up to 30 bits)
count
stove
(unnamed field)
radio
(padding up to 23 bits)
flag
(padding up to 31 bits)
Storage Occupied
1 bit
1 bit
To the next int boundary
The size of an int (4 bytes)
4 bits
4 bits
1 bit
To the next int boundary
(unnamed field)
1 bit
To the next int boundary
16 bytes = 64 bits
www.tenouk.com,
Total
1 bit
1 bit
30 bits
4 x 8 = 32 bits
4 bits
4 bits
1 bit
23 bits
1 bit
31 bits
4 x 32 bits = 128 bits
Total
32 bits
32 bits
32 bits
32 bits
128 bits
19/93
When you assign to a bit field a value that is out of its range, the bit
pattern is preserved and the appropriate bits are assigned.
The following expression sets the fridge field of the onoffpower
structure to 0 because only the least significant bit is assigned to the
fridge field,
onoffpower.fridge = 2;
But the following expression sets the fridge field of the onoffpower
structure to 1.
onoffpower.fridge = 5;
www.tenouk.com,
20/93
www.tenouk.com,
21/93
22/93
23/93
24/93
25/93
26/93
Suppose you would like to store and manipulate the record of 100
students.
It would be tedious and unproductive to create 100 different student
array variables and work with them individually.
It would be much easier to create an array of student structures.
Structures of the same type can be grouped together into an array.
We can declare an array of structures just like we declare a normal
array variable.
e.g., for 100 student records, we can declare a structure like the
following,
struct student{
int nIdNum, nAge;
char chName[80];
char chGender;
}studRecord[100];
www.tenouk.com,
27/93
28/93
29/93
www.tenouk.com,
30/93
www.tenouk.com,
31/93
So, take
note on
the
difference
between
an array
of
structure
and
structure
containing
array.
www.tenouk.com,
32/93
www.tenouk.com,
33/93
34/93
When the function readpart() is called, memory is allocated for all of its local
variables, including the struct inventory variable, part.
As each data item is read, it is placed in the corresponding field of part,
accessed with the dot operator.
The value of part is then returned to main() where it is assigned to the variable
items.
As would be the case for a scalar data type, the value of the return expression is
copied back to the calling function.
Since this is a structure, the entire structure (each of the fields) is copied.
For our inventory structure, this isn't too bad because only two floats and an
integer.
If structure having many members or nested, many values would need to be
copied.
For call to printpart(), an inventory structure is passed to the function.
Recall that in C, all parameters are passed by value, hence the value of each
argument expression is copied from the calling function into the cell allocated for
the parameter of the called function.
Again, for large structures, this may not be a very efficient way to pass data to
functions.
www.tenouk.com,
35/93
36/93
The code is very similar previous example, but we have changed the
prototypes and functions to work with pointers.
The argument of readpart() function is a pointer to the inventory
structure.
While items variable declared in main() is inventory structure
type.
The function accesses the object pointed to by pPartPtr, and uses
the dot operator to access a member of that object.
37/93
www.tenouk.com,
38/93
39/93
www.tenouk.com,
40/93
41/93
"path-spec"
<path-spec>
42/93
Quoted
form
Anglebracket
form
Action
This form instructs the preprocessor to look for include
files in the same directory of the file that contains the
#include statement, and then in the directories of
any files that include (#include) that file. The
preprocessor then searches along the path specified
by the /I compiler option (MS VC++), then along
paths specified by the INCLUDE environment variable.
This form instructs the preprocessor to search for
include files first along the path specified by the /I
compiler option (MS VC++), then, when compiling
from the command line, along the path specified by
the INCLUDE environment variable.
www.tenouk.com,
43/93
44/93
www.tenouk.com,
45/93
www.tenouk.com,
46/93
Step: Next we add (in this case we just cut and paste from
#endif
www.tenouk.com,
47/93
48/93
49/93
www.tenouk.com,
50/93
www.tenouk.com,
51/93
www.tenouk.com,
52/93
www.tenouk.com,
53/93
54/93
55/93
typedef
typedef declaration do not introduce new type but
introduces new name or creating synonym (or alias) for
existing type.
To construct shorter or more meaningful names for types
already defined by the language or for types that you have
declared.
A typedef declaration does not reserve storage.
The name space for a typedef name is the same as other
ordinary identifiers.
Therefore, a program can have a typedef name and a
local-scope identifier by the same name.
The exception to this rule is if the typedef name specifies a
variably modified type. In this case, it has block scope.
The syntax is,
typedef
type-declaration
www.tenouk.com,
the_synonym;
56/93
57/93
www.tenouk.com,
58/93
59/93
www.tenouk.com,
60/93
61/93
No tag
www.tenouk.com,
62/93
63/93
64/93
www.tenouk.com,
65/93
Can be typedef-ed,
// declare a structure with 3 members
typedef struct inventory{
int nPartNo;
float fBuyCost;
float fSellingPrice;
}abcinventory;
www.tenouk.com,
66/93
Should become
// variable of type struct abcinventory
abcinventory items;
www.tenouk.com,
67/93
And
// for declaration of variable of type tag
enum tag declarator;
68/93
69/93
70/93
www.tenouk.com,
71/93
72/93
73/93
74/93
75/93
www.tenouk.com,
76/93
www.tenouk.com,
77/93
78/93
www.tenouk.com,
79/93
80/93
The size is the size of the biggest element which is an array of float (20 x 4
bytes = 80 bytes).
www.tenouk.com,
81/93
82/93
If we put the some of the printf() at the end of source code, structure will
generate the expected output but not for union, because the last printf()
access will overwrite the previous stored data or at least the result is
unreliable.
Union, array and pointers program example: structure member access
www.tenouk.com,
83/93
www.tenouk.com,
84/93
85/93
86/93
87/93
union
member-list
88/93
89/93
www.tenouk.com,
90/93
91/93
92/93
93/93