Programming in C
Chapter 10
Structures and Unions
Structures
Complex data types can be constructed from fundamental types
aggregate variables of different types
Example: information about a playing card
struct card {
int pips;
char suit;
} ;
Variable declaration:
members
struct card c1, c2;
Variables may also be declared in the structure definition:
struct card {
int pips;
char suit;
} c1, c2 ;
Structure types
The variable type is struct card not just card.
Use typedef to define the type card to be equivalent
to the type struct card:
typedef
struct card
card
now the variable type really is just “card”.
Variable declaration:
card c3, c4, c5;
Alternatively, typedef may be used directly in conjunction with
struct without defining the tag name card first:
typedef struct {
int pips;
char suit;
} card ;
card can now be used as a variable type.
Using structures
Structures can contain any C-type,
including arrays, pointers or other structures.
Initialisation of structures: (similar to arrays)
card c3 = {13,’h’}; /* the king of hearts */
Assignment of structures:
c2 = c1;
assigns to each member of c2 the value
of the corresponding member of c1.
Arrays of structures:
card deck[52];
declares an array (of size 52) of variables
of type “card”; the name of the array is “deck”.
Accessing members of a structure:
c1.pips = 3;
c1.suit = ‘s’;
members of the structure are accessed
with the operator “.” (dot),
Example: Student grades
struct student{
char *last_name;
int student_id;
char grade;
};
Define the structure first. This would
probably go in a separate header file, e.g.
“student.h”
Note that here we haven’t yet assigned the
space for the string last_name – just for a
pointer to it – so we must use calloc or
malloc to allocate space for it
int main(void)
{
struct student tmp, class[100]; /*declaration
....
class[ ] is an array of structures
tmp.grade = ‘A’;
tmp.last_name = “Casanova”;
“Casanova” is defined here
tmp.student_id = 910017;
before compilation. Normally
}
you’d use calloc/malloc.
int fail(struct student class[ ])
{
int i, cnt = 0;
Count the failing grades
for (i = 0; i < 100; ++i)
cnt += (class[i].grade == ‘F’);
return cnt;
increment the counter if
}
grade is equal to ‘F’
Example: student grades
If the size of the class isn‘t known at compile time, dynamic allocation
must be used:
struct student *class
/*... read in number of students n...*/
class = (struct student *)
calloc(n,sizeof(struct student));
The variable *last_name within the structure is a pointer, pointing to a
string of appropriate length.
Alternatively, a maximum length string could have been defined to hold the
names:
struct student{
char last_name[MaxSize];
int student_id;
char grade;
};
Pointers to structures
Structures may contain large amounts of data
Use pointers to pass structures to functions
instead of moving them in memory
If a function should modify the contents of a structure:
Use pointers to pass structures to functions
instead of passing the structure by value.
Pointers to structures
struct student *p=&tmp;
Accessing a member with a dereferenced pointer use brackets,
because . has higher priority than *
(*p).grade;
This is so important that an equivalent syntax is provided
(saving two keystrokes)
p->grade;
Example: Complex numbers
Header file complex.h
struct complex {
double re;
/* real part */
double im;
/* imag. part */
};
typedef struct complex complex;
Function using complex data structure
#include “complex.h”
void add(complex *a, complex *b, complex *c)
/* *a = *b + *c
*/
{
a->re = b->re + c->re;
More to come
a->im = b->im + c->im;
}
in homework!
Structures as members of structures
Structures can contain other structures as members
Example: employer’s database
struct dept {
char dept_name[25];
int
dept_no;
};
typedef struct {
char
int
struct dept
struct address
double
.....
} employee_data;
Members structures must be
defined beforehand, since the
compiler must know their size
name[25];
employee_id;
department;
*a_ptr;
salary;
The size of a pointer to a structure is just
the size of the address and therefore known.
Struct address can be defined later.
Updating structures in functions: method 1
Send structure e down to the function, modify it, and return the
modified structure for use in the calling routine:
e = update1(e);
.....
Within calling routine,
e.g. function main()
employee_data update1(employee_data e)
{
....
printf (“Input the department number: ”);
scanf(“%d”, &n);
/* now access member of struct-within-struct... */
e.department.dept_no = n;
.....
return e;
}
This involves a lot of copying of structure members down to the
function and back again. There’s a better way...
Updating structures in functions: method 2
Passing a pointer to a data structure is more efficient:
update2(&e);
Within calling routine (e.g.
function main() ), to pass
address to update function
void update2(employee_data *p)
{
....
printf(“Input the department number:
scanf(“%d”, &n);
p->department.dept_no = n;
.....
}
”);
Use -> instead of . to access
structure member, because p
is a pointer to the structure
Example: Playing poker
The program in ....lect9/poker.c is a model of a poker-playing program.
It repeatedly shuffles and deals a set of five cards to each of six players,
and then calculates the probability that a flush is dealt (i.e. that all five
cards are of the same suit).
Look at the code, and run it. The probability of a flush (all cards the
same suit) is 0.00198... How close does this program come if you run it
several times?
Note that the card structure in the code uses an enumerated type to
define the suit. Note also that deck[52] is an array, and the variable
name “deck[52]” is therefore equivalent to a pointer to the start of the
array – the whole array of 52 structures is not passed down with each
function call that has deck[ ] as an argument!
Union
union int_or_float {
int i;
float f;
}
typedef union int_or_float {
int
i;
float f;
} number;
int main(void)
{
number n;
n.i = 4444;
printf("i: %10d
f: %16.10e\n", n.i, n.f);
n.f = 4444.0;
printf("i: %10d
return 0;
}
f: %16.10e\n", n.i, n.f);
© Copyright 2026 Paperzz