Title: Topic 11
1Topic 11 Structures and Unions
2Introduction to Structures
- We have seen that an array is a list of the same
type of elements. - A structure is a collection of differing data
types. It is usually used to implement a record
(as in a database record). - For example, a good use of a structure would be
to represent a students record in a class /
grading database.
3Introduction to Structures
- For each student, the program needs to store the
students last, middle, and first names, their
student ID number, their numerical grade (course
average) and their final course grade. - Thus, for each student record, we need four
strings (each name and the ID number), a float
(numerical grade), and a character (letter grade).
4Introduction to Structures
- Thus, we can define a structure to hold a student
record as - typedef struct
- char last20
- char middle20
- char first20
- float numerical_grade
- char letter_grade
- student_record
5Structures
- What this structure definition does is to define
a new data type, named student_record. - This new data type holds three strings of 20
characters each, one floating point number, and
one character.
typedef struct char last20 char
middle20 char first20 float
numerical_grade char letter_grade
student_record
Then, inside the braces, we list (declare) the
member variables that will compose the structure.
6Structures
- A structure definition goes outside of any
function, including main(). - This is similar to function prototypes which
precede main. A good idea is to place structure
definitions immediately before function
prototypes. - Once the structure definition is present,
variables of the structure data type can now be
declared inside functions.
7Structures
typedef struct char last20, middle20,
first20 float numerical_grade char
letter_grade student_record int
main() float a, b, c student_record
TopStudent student_record others175 int x,
y, z . . .
8Structures
- Note that for each variable of type
student_record, we can store 3 strings, 1
floating point number, and one character. - So, the question remainshow do we access all of
these variables contained within our new
programmer-designed data type?
9Structure Component Referencing
- To do this, we can use the direct component
selection operator, also known as a period . - In our previous example, to reference the last
name string (named last) inside the variable
TopStudent, we would write - TopStudent.last
10Structure Component Referencing
student_record TopStudent student_record
others175 strcpy(TopStudent.last,Six) strc
py(TopStudent.middle,Alan) strcpy(TopStudent.fi
rst,Jeffrey) TopStudent.numerical_grade
100 TopStudent.letter_grade A printf(The
top student was\n) printf(s s s who got a
f which is a c.\n, TopStudent.first,
TopStudent.middle, TopStudent.last,
TopStudent.numerical_grade, TopStudent.letter_grad
e)
11Structure Component Referencing
- We can see that a structure component (one of the
variables that make up the structure) can be
accessed using the . operator. - Thus, variable_name.component_name can be used in
the exact same way as a regular variable of the
same type.
12Structure Component Referencing
- Looking at our previously example,
TopStudent.numerical_grade can be used in any
manner a float data type can be.
TopStudent.letter_grade can be used just like any
other character. - Also, others9.numerical_grade can be used like
any other float and others9.letter_grade can be
used just like any other char.
13Array Structure Referencing
- Notice that in the reference
- others9.letter_grade
- We can see that the array referencing
operator takes precedence over the structure
referencing operator . - Thus, first we use the operator to get one
student_record from the array of student_records
and then we use the . operator to get the
letter_grade floating point variable from within
that student_record.
14Structures as Function Arguments
- We can pass a structure into a function
void print_record(student_record
a) printf(Name s,s s\n, a.last,
a.first, a.middle) printf(Numerical Grade
f\n, a.numerical_grade) printf(Letter
Grade c\n, a.letter_grade)
15Structures asFunction Arguments
- We could write a function to compare two student
records (1 if true, 0 else)
int compare_records(student_record a,
student_record b) if (strcmp(a.last,b.last)
0 strcmp(a.middle,b.middle) 0
strcmp(a.first,b.first) 0
a.numerical_grade b.numerical_grade
a.letter_grade b.letter_grade) return
1 else return 0
16Structure Pointers
- Just like other variables, we can have pointers
that point to structures. As such, they will
contain the address of the structure in memory.
student_record TopStudent student_record
best_p best_p TopStudent
17Structure Pointers
- We can use pointers to structures in the same way
we can use pointers to other variables
student_record TopStudent student_record best_p
TopStudent strcpy((best_p).last,Six) (be
st_p).numerical_grade 100 printf(Student s
has a grade of f.\n, (best_p).last,(best_p)
.numerical_grade)
18Structure Pointers
Notice the precedence. The is put in parens
so we evaluate it first. This operator
dereferences the pointer, which gives us a
structure of type student_record. The .
operator has higher precedence than the
operator so it is evaluated next, giving us the
component. Finally, the operator
is evaluated, giving the address that scanf needs.
- We can also use structure pointers to make a
structure function output parameter
int read_record(student_record record_p) int
result result scanf(s s s f
c, (record_p).last, (record_p).middle, (
record_p).first, (record_p).numerical_grade,
(record_p).letter_grade) if (result 5)
return 1 else return 0
19Structure Pointers
- The precedence issue can get confusing. As the
. operator has higher precedence than the
operator, the pointer name and the dereferencing
operator must be put in parens if we want to
access a structure component using a pointer. - Fortunately, C provides a much cleaner operator
to remedy this confusing situation.
20Structure Pointers
- C provides the indirect component selection
operator -gt. This is a dash followed by a
greater-than sign, which forms an arrow-like
operator. - This new, indirect operator takes a pointer to a
structure variable on the left side and the
component name to be accessed on the right side. - This is a contrast to the direct component
selection operator . This operator takes a
structure variable on the left side and the
component name to be accessed on the right side.
21Structure Pointers
- Thus, the following expressions are equivalent
- (best_p).last best_p-gtlast
- (best_p).first best_p-gtfirst
- (best_p).letter_grade
- best_p-gtletter_grade
- Note that either form is correct, however, the
form on the right side is more clear and
straight-forward.
22Structure Pointers
- Thus, we can rewrite our function output
parameter example
int read_record(student_record record_p) int
result result scanf(s s s f
c, record_p-gtlast, record_p-gtmiddle, recor
d_p-gtfirst, record_p-gtnumerical_grade, recor
d_p-gtletter_grade) if (result 5) return 1
else return 0
23Functions Returning Structures
- Structures can also be used as function return
types
student_record read_record(void) student_record
input_record result scanf(s s s f
c, input_record.last, input_record.middle,
input_record.first, input_record.numerical_gra
de, input_record.letter_grade) return
input_record
24Functions Returning Structures
- We would call this function is the same manner as
a function that returns any other datatype.
student_record record1 record1 read_record()
25Unions
- A union is very similar to a structure, except
that where a structure contains all of the
variables present in their definitions, a union
contains any one of the variables present in
their definitions. - A union is declared as
typedef union int wears_wig char
color20 hair_data
26Unions
typedef union int wears_wig char
color20 hair_data
- This definition says that a variable of type
hair_data contains either an integer named
wears_wig or a 20 character string named color. - A component of a union is accessed the same way a
structure component is, using the . operator or
the -gt operator.
27Unions
- Note that when a variable is declared that is a
union type, space is allocated in memory for the
largest of the component variables. - If the program accesses the union variable using
the integer component name, the memory for that
union variable is treated as a integer. If the
program accesses the union variable using the
string component name, the memory for the union
variable is treated as a string.
28Unions
- Therefore, once a union variable is used, i.e. it
is referenced using one of its components, it is
important to ONLY use that component name to
reference the union variable in further
statements. - If the program first uses the previous union
using the component wears_wig (an integer), an
integer will be stored at the memory allocated
for that union variable.
29Unions
- If, at a later point, the program references the
union using the component color (a string), it
will attempt to find a string at the memory
allocated for the union variable. - As we previously put an integer there, this will
cause an unpredictable result. - Sofor each union-type variable, use only one
component. And use only that component for that
variable throughout the program. Anything else
will cause errors!
30Summary
- A structure is a programmer-defined datatype that
is a record (a collection of variables of varying
datatypes). - An individual component of a structure can be
accessed using a structure variable name and the
. operator. - We can make a pointer to a structure in the same
way we can make a pointer to any other datatype.
31Summary
- An individual component of a structure can be
access using a pointer to a structure and the
-gt operator. - A union is similar to a structure except that
containing all of the component variables, it
contains ONE. - Once a union-type variable is declared and
referenced using one of its components, that
variable can only be referenced using that
component throughout the program.