EE3490E - Fundamentals of
Embedded Programmings
Chapter 4: Data
Structures & Algorithms
© DIA 2020.2
Content
4.1. Introduction of data structures
4.2. Arrays and dynamic memory management
4.3. Vector structure
4.4. List structure
4.5. Sorting algorithms
4.6. Recursion
4.7. Bitwise operation
4.8. Event-driven programming
Chapter 4: Data Structures & Algorithms © DIA 2020.2 2
4.5 Sorting algorithms
Objective: rearrange a given array or list elements
according to a comparison operator on the elements.
The comparison operator is used to decide the new
order of element in the respective data structure.
Ascending order: from the smallest to the largest number
Descending order: from the largest number to smallest number
Problem statement:
Input: given an array a of size n: a[0], a[1], …, a[n-1]
Output: a permutation (reordering) of a (a’[0], a’[1], …, a’[n-
1] in such a way that:
• a’[0] <= a’[1] <= ... <= a’[n-1]
Chapter 4: Data Structures & Algorithms © DIA 2020.2 85
Sorting algorithms
A number of applications in reality:
Commercial computing. Government organizations, financial institutions, and
commercial enterprises organize much of this information by sorting it
Search for information. Keeping data in sorted order makes it possible to
efficiently search through it. E.g.: sorting the number of access of websites
using a search engine like Google
String processing algorithms are often based on sorting
As fundamental algorithm to solve more complex problems such as numerical
computations, operations research, optimization, etc.
Early sorting algorithms were proposed in 1950s such as bubble sort,
merge sort, quick sort, etc.; new ones are still being invented
References:
Cormen, Thomas H., and Thomas H. Cormen. 2001. Introduction to algorithms.
Cambridge, Mass: MIT Press.
Robert Sedgewick and Kevin Wayne. 2011. Algorithms (4th. ed.). Addison-
Wesley Professional.
2 algorithms will be introduced: selection sort and merge sort
Chapter 4: Data Structures & Algorithms © DIA 2020.2 86
Sorting algorithms
Input data
0 n-1
a Unsorted
Desired output:
Data has been sorted in certain order
0 n-1
a Sorted array: a[0]<=a[1]<=…<=a[n-1]
Chapter 4: Data Structures & Algorithms © DIA 2020.2 87
4.5.1 Selection sort
Initial state
0 n-1
The smallest numbers The remaining data,
a which have been sorted unsorted
Steps:
Find the smallest number in a[k..n-1]
Swap a[k] and the smallest number we found above
0 n-1
The smallest numbers
a which have been sorted
a[k] x
Chapter 4: Data Structures & Algorithms © DIA 2020.2 88
Find the smallest number
/* Yield location of smallest element
in a[k..n-1] */
/* Assumption: k < n */
/* Returns index of smallest, does not return the
smallest value itself */
int min_loc (int a[], int k, int n) {
/* a[pos] is smallest element found so far */
int j, pos;
pos = k;
for (j = k + 1; j < n; j = j + 1)
if (a[j] < a[pos])
pos = j;
return pos;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 89
Selection sort
/* Sort a[0..n-1] in non-decreasing
order (rearrange
elements in a so that
a[0]<=a[1]<=…<=a[n-1] ) */
int sel_sort (int a[], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 90
Example
Chapter 4: Data Structures & Algorithms © DIA 2020.2 91
Example
Chapter 4: Data Structures & Algorithms © DIA 2020.2 92
Example
Chapter 4: Data Structures & Algorithms © DIA 2020.2 93
Algorithm evaluation
How many iterations do we need to sort n numbers?
Before swapping position, it is needed to check through the
whole unsorted part of the array
The length of unsorted part in the initial array is n
The algorithm repeats n iterations of checking/swapping
Total of steps is proportional to
Conclusion: selection sort is pretty slow with large
arrays
Chapter 4: Data Structures & Algorithms © DIA 2020.2 94
Better algorithm?
Algorithms with complexity of nlogn
Merge sort
Quick sort
When array size grows, time taken to execute
algorithms with complexity of n2 is much higher than
that with nlogn complexity
Chapter 4: Data Structures & Algorithms © DIA 2020.2 95
4.5.2 Merge sort
Basic idea:
Starting with sorted arrays: pointers are at the beginning of the
arrays
Use the pointer to mix the position of each pair of elements
within sorted arrays to make a bigger array with sorted
elements
After merging 2 arrays, we get the desired array eventually
The basic operator is merging
Chapter 4: Data Structures & Algorithms © DIA 2020.2 96
Merge sort
Chapter 4: Data Structures & Algorithms © DIA 2020.2 97
Merge sort
Chapter 4: Data Structures & Algorithms © DIA 2020.2 98
Merge sort
Chapter 4: Data Structures & Algorithms © DIA 2020.2 99
Merge sort
We need n comparisons and copying data n times, thus
the workload is proportional to n
However, this is not yet a sorting algorithm
So how to do?
Chapter 4: Data Structures & Algorithms © DIA 2020.2 100
Merge sort implementation
It is needed to know the position of pointers to merge
the respected arrays together
At the starting point, each element in the array is a
pointer
Merge sort:
Merge each pair of 1-element arrays to be a 2 element array
Merge each pair of 2-element arrays to be a 4 element array
Merge each pair of 4-element arrays to be a 8 element array
And so on until completing
Chapter 4: Data Structures & Algorithms © DIA 2020.2 101
Example
Chapter 4: Data Structures & Algorithms © DIA 2020.2 102
Example
Sorting task is done
Each merging step take a duration proportional to n
How many time do we merge? It is 3 in this example
In general, we need log2n merging steps
When n =8:
Total time consumed is proportional to nlog2n (or
nlogn).
Chapter 4: Data Structures & Algorithms © DIA 2020.2 103
In short
Chapter 4: Data Structures & Algorithms © DIA 2020.2 104
Any approach performed better
than nlogn?
In general, the answer is NO
However, in some special cases, we may do better
E.g.: sorting exam papers based on the scores put the
papers into one of 10 piles with respect to their scores
required time is proportional to n.
The performance of the algorithm can be evaluated via
mathematical calculation without using computer
This specific area in mathematics is approximation theory.
There are a lot of interesting topics to be solved
E.g.: The P versus NP problem: Whether every problem
whose solution can be quickly verified can also be solved
quickly
Chapter 4: Data Structures & Algorithms © DIA 2020.2 105
Efficiency
The resources can be saved
It is usually measured by execution duration and
memory space required
A lot of details in programming has little or no effect on
efficiency
It is often achieved by selecting the right algorithm
and/or data structure
Chapter 4: Data Structures & Algorithms © DIA 2020.2 106
4.5.3 Structure and Array
A structure represent a simple data record, computer
program processes a set of data records
E.g.: student record, staff record, customer record, etc.
In each case, there are a number of variables, thus it
would require to use an array of structure to store data
Chapter 4: Data Structures & Algorithms © DIA 2020.2 107
Example
#define MAX_NAME 40 typedef struct {
typedef struct { int hours, minutes;
char name [MAX_NAME+1]; double seconds;
int id; } time;
double score;
} student_record; typedef struct {
double x, y ;
} point;
Chapter 4: Data Structures & Algorithms © DIA 2020.2 108
Array of structure
Each statement below shows the declaration of an array
in which each element is a structure
point corner_points[10];
time meeting_times[MAX_MEETINGS];
student_record tdh_34[MAX_STUDENTS];
The fields of structure are accessed via the array
element and the field names
cse_142[i].name
corner_points[j+1].x
meeting_times[4].hours
Chapter 4: Data Structures & Algorithms © DIA 2020.2 109
Array of structure
point pentagon[5];
Array of structure pentagon
x
y
pentagon[1] – structure
x
y
x
y pentagon[4].x – a real number
x
y
x
y
Chapter 4: Data Structures & Algorithms © DIA 2020.2 110
Array of structure
student_record class[MAX_STUDENTS];
...
for (i = 0; i < nstudents; i = i + 1)
{
scanf(“%d %d”, &class[i].hw, &class[i].exams);
class[i].grade =
(double) (class[i].hw+class[i].exams) / 50.0;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 111
Array element as argument
void draw_line (point p1, point p2) {.....}
...
point pentagon[5];
...
for (i = 0; i < 4; i = i + 1) {
draw_line(pentagon[i], pentagon[i+1]);
}
draw_line(pentagon[4], pentagon[0]);
Chapter 4: Data Structures & Algorithms © DIA 2020.2 112
Revision on passing a value
A structure variable is passed with its value
All the fields of the variable are copied to initialize the
argument
point midpoint (point a; point b) {...}
int main (void) {
point p1, p2, m; /* declare 3 points */
...
m = midpoint(p1, p2);
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 113
Revision on passing an array
An array of element is an array
When the array is used as a parameter in function call,
it needs to be passed by using reference
The reference is actually an alias of the input parameter
int avg (student_rec class_db[MAX_N]) {...}
int main (void) {
student_rec ktlt_k50[MAX_N];
int average;
....
average = avg(ktlt_k50); /*by reference*/
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 114
Sorting an array of structure
David Kathryn Sarah Phil Casey
920915 901028 900317 920914 910607
2.9 4.0 3.9 2.8 3.6
Phil David Casey Sarah Kathryn
920914 920915 910607 900317 901028
2.8 2.9 3.6 3.9 4.0
typedef struct {
char name[MAX_NAME + 1];
int id;
double score;
} StudentRecord;
Chapter 4: Data Structures & Algorithms © DIA 2020.2 115
Revision of selection sort
int min_loc (int a[ ], int k, int n) {
int j, pos; pos = k;
for (j = k + 1; j < n; j = j + 1)
if (a[j] < a[pos])
pos = j;
return pos;
}
void swap (int *x, int *y);
void sel_sort (int a[ ], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 116
Sorting an array of structure
Initially, it is required to identify the field to sort by
E.g.: sort by scores
Change the data type of the array to StudentRecord
Rewrite the code for comparison in min_loc function
Write swap function for StudentRecord
Chapter 4: Data Structures & Algorithms © DIA 2020.2 117
Sorting an array of structure
int min_loc (StudentRecord a[ ], int k, int n) {
int j, pos; pos = k;
for (j = k + 1; j < n; j = j + 1)
if (a[j].score < a[pos].score)
pos = j;
return pos;
}
void swap (StudentRecord *x, StudentRecord *y);
void sel_sort (StudentRecord a[ ], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 118
Sorting by alphabetic order
David Kathryn Sarah Phil Casey
920915 901028 900317 920914 910607
2.9 4.0 3.9 2.8 3.6
Casey David Kathryn Phil Sarah
910607 920915 901028 920914 900317
3.6 2.9 4.0 2.8 3.9
typedef struct {
char name[MAX_NAME + 1];
int id;
double score;
} StudentRecord;
It is required to write a function for comparing two strings
Chapter 4: Data Structures & Algorithms © DIA 2020.2 119
String compare revision
“Alice” < “Bob”
“Dave” < “David”
“Rob” < “Robert”
#include <string.h>
int strcmp(char str1[ ], char str2[ ]);
Returning value is
A negative number if str1 < str2
Zero if str1 = str2
A positive number if str1 > str2
Chapter 4: Data Structures & Algorithms © DIA 2020.2 120
Sorting by alphabetic order
int min_loc (StudentRecord a[ ], int k, int n) {
int j, pos; pos = k;
for (j = k + 1; j < n; j = j + 1)
if (0 > strcmp(a[j].name, a[pos].name))
pos = j;
return pos;
}
void swap (StudentRecord *x, StudentRecord *y);
void sel_sort (StudentRecord a[ ], int n) {
int k, m;
for (k = 0; k < n - 1; k = k + 1) {
m = min_loc(a,k,n);
swap(&a[k], &a[m]);
}
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 121
Thinking in data structure
If we want to store information of a song in a computer
What kind of information needs to be stored?
How to organize the information?
How to implement in C?
And if
We need information of a CD
Or information of a set of CDs
Chapter 4: Data Structures & Algorithms © DIA 2020.2 122
Insertion sort
/* sort student records a[0..size-1] in */
/* ascending order by score */
void sort (student_record a[ ], int size)
{
int j;
for (j = 1; j < size; j = j + 1)
insert(a, j);
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 123
Insertion sort
/* given that a[0..j-1] is sorted, move a[j]
to the correct location so that that a[0..j]
is sorted by score */
void insert (student_record a[ ], int j) {
int i;
student_record temp;
temp = a[j];
for (i = j; i > 0 &&
a[i-1].score > temp.score; i = i-1) {
a[i] = a[i-1];
}
a[i] = temp;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 124
Insertion sort
/* given that a[0..j-1] is sorted, move a[j] to
the correct location so that that a[0..j] is
sorted by score */
void insert (student_record a[ ], int j) {
int i;
student_record temp;
temp = a[j];
for (i = j; i > 0 &&
strcmp(a[i-1].name, temp.name) > 0;
i = i-1) {
a[i] = a[i-1];
}
a[i] = temp;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 125
4.6. Recursion
It’s possible for a function to call itself. This is termed
recursion
int foo(int x) {
...
y = foo(...);
...
}
Questions:
How recursion works?
• To be discussed
Why do we need recursive functions?
• We will see the motivations
Chapter 4: Data Structures & Algorithms © DIA 2020.2 126
4.6.1 Factorial function
Function name
Parameter/
int factorial(int n) Argument
{
int product, i;
product = 1; Local variables
Type and for (i = n; i > 1; i = i - 1)
returning {
value product = product * i; 0! = 1
} 1! = 1
2! = 1 * 2
return (product);
3! = 1 * 2 * 3
} ...
Chapter 4: Data Structures & Algorithms © DIA 2020.2 127
Factorial function using recursion
The definition of factorial function is recursive itself
0! = 1! = 1; for n > 1, n! = n(n-1)!
int factorial(int n) 0! is 1
{ 1! is 1
int t; n! is n * (n-1)!, for n>1
if (n <= 1)
E.g.: 3! = 3 * 2!
t = 1;
= 3 * 2 * 1!
else =3*2*1
t = n * factorial(n - 1);
return t;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 128
Function revision
It does not take much effort to trace the recursive
function if we remember the background of functions:
Arguments and variables declared in a functions is the local
variable of that function
• They are allocated memory space once the function is called
• The allocated memory is free when exiting the function
Arguments are initialized by copying values of the passing
variables in function call
Chapter 4: Data Structures & Algorithms © DIA 2020.2 129
Factorial function
factorial(4) =
4 * factorial(3) =
4 * 3 * factorial(2) =
4 * 3 * 2 * factorial(1) =
4 * 3 * 2 * 1 = 24
Chapter 4: Data Structures & Algorithms © DIA 2020.2 130
‘y’ or ‘n’ question
char yes_or_no(void)
{
char answer = ‘X’;
while(answer != ‘y’ && answer != ‘n’)
{
printf (“Please enter ‘y’ or ‘n’:”);
scanf (“%c”, &answer);
}
return answer;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 131
Implementation without loop
char yes_or_no(void)
{
char answer;
printf (“Please enter ‘y’ or ‘n’:”);
scanf (“%c”, &answer);
if(answer != ‘y’ && answer != ‘n’)
answer = yes_or_no( );
return answer;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 132
Loop and Recursion
Any algorithm using loop can be replaced by recursion
and vice versa
In some languages, recursion is the only choice
Some algorithms are represented as recursion naturally:
It is not effective if employing recursive function for simple
algorithms/application
Chapter 4: Data Structures & Algorithms © DIA 2020.2 133
When to use recursion
Some cases, the problem can be solved by transforming
to simple cases
Continuously carrying out transformation until a simple
operation which is not recursive is obtained
Chapter 4: Data Structures & Algorithms © DIA 2020.2 134
4.6.2 Towers of Hanoi
Tower of Hanoi is a mathematical puzzle where we
have 3 rods (towers) and n disks.
The objective is to move all the disks to another rod,
Rules to be followed:
1) Only one disk can be moved at a time.
2) Only the "top" disk can be removed
3) No disk may be placed on top of a smaller disk.
1
2
3
A B C
Chapter 4: Data Structures & Algorithms © DIA 2020.2 135
Towers of Hanoi
Following is an animated representation of solving a Tower
of Hanoi puzzle with three disks.
Tower of Hanoi puzzle with n disks can be solved in
minimum 2n−1 steps. This presentation shows that a puzzle
with 3 disks has taken 23 - 1 = 7 steps.
Assume that we have 64 disks, if time taken to move 1 disk
is t [seconds]
Total required time is:
Let :
1 1
2 2 1
13 31 2
A B C
Chapter 4: Data Structures & Algorithms © DIA 2020.2 136
Towers of Hanoi
Move n disks from tower X
to tower Z by using Y as an
intermediate tower
(1) Move (n-1) disks from tower X to
tower Y by using Z as an intermediate
tower as the top disks are smaller
(2) Move disk n (the largest) from X to
Z
(3) Repeat the procedure for the
remaining n-1 disks in tower Y to Z
with the intermediate tower X
Chapter 4: Data Structures & Algorithms © DIA 2020.2 137
4.6.3 Quick sort - Example
Sorting the following integer array
40 20 10 80 100 50 7 30 60
Chapter 4: Data Structures & Algorithms © DIA 2020.2 138
Select the ‘pivot’ element
Choose the element to be compared with: e.g. select the
first element
40 20 10 80 60 50 7 30 100
Chapter 4: Data Structures & Algorithms © DIA 2020.2 139
Divide the array into smaller ones
Given number of elements, dividing the array into 2:
The first array includes elements the pivot one
The other include elements the pivot one
7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]
<= data[pivot] > data[pivot]
Chapter 4: Data Structures & Algorithms © DIA 2020.2 140
Recursion: Quicksort Sub-arrays
7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]
<= data[pivot] > data[pivot]
Chapter 4: Data Structures & Algorithms © DIA 2020.2 141
Quicksort Analysis
Assume that keys are random, uniformly distributed.
What is best case running time?
Recursion:
1. Partition splits array in two sub-arrays of size n/2
2. Quicksort each sub-array
Depth of recursion tree? O(log2n)
Number of accesses in partition? O(n)
7 20 10 30 7 20 10 7 10 20
Chapter 4: Data Structures & Algorithms © DIA 2020.2 142
Quicksort Analysis
Assume that all elements are randomly distributed
Shortest duration: O(n log2n)
How about the worst case scenario?
Chapter 4: Data Structures & Algorithms © DIA 2020.2 143
Quicksort: the worst case
Assumed that all the elements are distributed
ascendingly
pivot_index = 0 2 4 10 12 13 50 57 63 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]
Chapter 4: Data Structures & Algorithms © DIA 2020.2 144
Another approach to choose the
pivot
Select the mean of 3 elements in the array
data[0], data[n/2], and data[n-1].
Use this mean value as the pivot
Chapter 4: Data Structures & Algorithms © DIA 2020.2 145
Optimizing Quicksort
Find the pivot element
If the size is smaller or equal to 3:
One element: do nothing
If there is 2 elements: if(data[first] > data[second]) swap them
If there is 3 elements: homework
Chapter 4: Data Structures & Algorithms © DIA 2020.2 146
Micromouse
Chapter 4: Data Structures & Algorithms © DIA 2020.2 147
Example
/* ‘F’ means finished! 0
‘X’ means blocked 1
‘ ’ means ok to 2
move */ 3
char maze[MAXX][MAXY]; y 4
/* start in yellow */ 5
6
int x =0, y=0;
7
Unless it finds the obstacle, 8
robot can move up, down, F
left, right 9
0 1 2 3 4 5 6 7
Problem: does a route to the x
destination exist?
Chapter 4: Data Structures & Algorithms © DIA 2020.2 148
Simple cases
Assume that robot is at 0
the position (x,y) 1
if maze[x][y] == ‘F’ 2
• then “yes!” 3
if no place to go 4
y
• then “no!” 5
6
7
8
9 a F
0 1 2 3 4 5 6 7
x
Chapter 4: Data Structures & Algorithms © DIA 2020.2 149
Make it simpler
0 0
It is not necessary to go 1 1
through a cell twice 2 2
3 3
4 4 ...
0 5 5
1 6 6
2 7 7
3 8 8
9 F 9 F
4 or
5 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
6
7 0
8 1
9 F 2
0 1 2 3 4 5 6 7 3
4
5
...
6
7
8
9 F
Chapter 4: Data Structures & Algorithms 0 1 2 3 4 5 6 7© DIA 2020.2 150
Supporting function
/* Returns true if <x,y> is a legal move
given the maze, otherwise returns false */
int legal_mv (char m[MAXX ][MAXY], int x, int y)
{
return(x >= 0 && x <= MAXX && y >= 0 &&
y <= MAXY && m[x][y] != ‘X’);
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 151
An elegant solution
/* Returns true if there is a path from <x,y> to an
element of maze containing ‘F’ otherwise returns
false */
int is_path (char m[MAXX][MAXY ], int x, int y) {
if (m [x][y] == ‘F’)
return(TRUE);
else {
m[x][y] = ‘X’;
return((legal_mv(m,x+1,y) && is_path(m,x+1,y)) ||
(legal_mv(m,x-1,y) && is_path(m,x-1,y)) ||
(legal_mv(m,x,y-1) && is_path(m,x,y-1)) ||
(legal_mv(m,x,y+1) && is_path(m,x,y+1)))
}
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 152
Example
is_path(maze, 7, 8) x
0
1
2
3
4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
Chapter 4: Data Structures & Algorithms © DIA 2020.2 153
Example
is_path(maze, 7, 8) x
is_path(maze, 7, 8)
0
1
2
3
4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
Chapter 4: Data Structures & Algorithms © DIA 2020.2 154
Example
is_path(maze, 7, 8) x
is_path(maze, 7, 8)
0
1
2
3
4
is_path(maze, 7, 8) 5
6
7
8
9 F
0 1 2 3 4 5 6 7
Chapter 4: Data Structures & Algorithms © DIA 2020.2 155
Recursion summary
Recursion is one of the programming techniques
Its principle is based on the manner that a function is called and
local variables are used in C
Every time, a function is called, everything has its new copy
It is also an approach to solve problems
It would take time and effort to master this
technique
Recursion is a natural way to work with a
number of data structures
Chapter 4: Data Structures & Algorithms © DIA 2020.2 156
4.7. Bitwise operation
C provides operators
To change each bit individually
To perform operations which are usually available in
Assembler only
The C program with bitwise operation can run in
different OS, however most of these kind of programs
are written to work in specific hardware
Chapter 4: Data Structures & Algorithms © DIA 2020.2 157
Negative numbers
Bit MSB (most significant bit) is 1, the number is
negative
Two’s complement to represent negative number, e.g.:
-22425 as a binary number: 1010 1000 0110 0111
The algorithm:
Subtract 1 from the original number 22425, we get 22424
Convert to binary
0101 0111 1001 1000
Perform 1’s complement by inverting each bit
1010 1000 0110 0111 = -22425
Chapter 4: Data Structures & Algorithms © DIA 2020.2 158
Bitwise operators
6 bitwise operators in C:
& | ^ ~ << >>
These operators are applicable with the data types:
char, short, int, long.
They can be used for floating point arithmetic
5 bit assignment operators
&= |= ^= <<= >>=
Bit assignment operators are similar to arithmetic
assignment operators
z &= x | y;
z = z & (x | y);
Chapter 4: Data Structures & Algorithms © DIA 2020.2 159
Bitwise operators
Attention: developers should not confuse bitwise
operators with logical operators
& | ~ << >>
&& || ! < >
Chapter 4: Data Structures & Algorithms © DIA 2020.2 160
AND &
Perform AND bit-by-bit operation of two integers
E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 & b2;
b1 00011001 25
b2 01001101 & 77
b3 00001001 9
It is used to
Reset bit
Select a bit to verify
Chapter 4: Data Structures & Algorithms © DIA 2020.2 161
OR |
Perform OR bit-by-bit operation of two integers
E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 | b2;
b1 00011001 25
b2 01101010 | 106
b3 01111011 123
It is used to
Set a bit
Chapter 4: Data Structures & Algorithms © DIA 2020.2 162
XOR ^
Perform XOR bit-by-bit operation of two integers
E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 ^ b2;
b1 00011001 25
b2 01001101 ^ 77
b3 01010100 84
It is used to
Set a bit
Chapter 4: Data Structures & Algorithms © DIA 2020.2 163
NOT ~
Perform NOT (1’s complement) operation of an integer
E.g.: b1, b2 are unsigned char numbers
b2 = ~b1;
b1 00011001 25
b2 11100110 230
It is used to
Invert status of a bit or a group of bits
Chapter 4: Data Structures & Algorithms © DIA 2020.2 164
Left shift <<
Perform left shift operation of an integer by a number
of bits specified by the right operand
E.g.: b1, b2 are unsigned char numbers
b2 = b1 << 2;
b1 00011010 26
b2 01101000 104
Attention:
MSB disappears, inserted bit at LSB is always 0
The operator is equivalent to multiplying the number with 2^n:
b2 = b1*4
Chapter 4: Data Structures & Algorithms © DIA 2020.2 165
Right shift >>
A bit more complex: shift the bits of an integer to the
right by a number specified by the right operand
LSB disappears, inserted bit at MSB is
0 if the number is unsigned
1 (arithmetical right shift) hoặc 0 (logical right shift)
signed char x = -75; /* 1011 0101 */
signed char y = x>>2; /* 0010 1101 (logical) */
/* 1110 1101 (arithmetic) */
The result depends on the computer and the OS.
It is 45 with logical right shift and -19 with arithmetical right
shift in the above example.
In fact, right shift is usually applied for unsigned numbers and
it is equivalent to dividing the number by 2^n
Chapter 4: Data Structures & Algorithms © DIA 2020.2 166
2 raised to the n-th power
Bit shift operators are often used in exchange of
multiplication
They are faster than multiply operator
x * 2 x << 1
x / 16 x >> 4
x % 8 x & 7
However, using bit shift operators make the code more
difficult to read
Chapter 4: Data Structures & Algorithms © DIA 2020.2 167
Warning
If bit shift operator is perform by a number larger than
size of (sizeof) the left operand, the result may be
unspecified
Chapter 4: Data Structures & Algorithms © DIA 2020.2 168
Bitwise operators precedence
Precedence of bitwise operators in C:
NOT ~
AND &
XOR ^
OR |
However, () should be used in all cases
Chapter 4: Data Structures & Algorithms © DIA 2020.2 169
Checksum 8 bit
#include <reg51.h> #include <reg51.h>
void main(void) { void main(void) {
unsigned char mydata[] unsigned char mydata[]
={0x25,0x62,0x3F,0x52}; ={0x25,0x62,0x3F,0x52,0xE8};
unsigned char sum=0, x unsigned char shksum=0;
unsigned char chksumbyte; unsigned char x;
for (x=0;x<4;x++) { for (x=0;x<5;x++)
P2=mydata[x]; chksum=chksum+mydata[x];
sum=sum+mydata[x]; if (chksum==0)
P1=sum; P0=‘Good’;
} else
chksumbyte=~sum+1; P0=‘Bad’;
P1=chksumbyte; }
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 170
Checksum 8 bit
#include <reg51.h> Summation:
void main(void) {
unsigned char mydata[]
25H+ 62H+ 3FH+ 52H = 118H
={0x25,0x62,0x3F,0x52}; Two complements of 118H
unsigned char sum=0, x
unsigned char chksumbyte;
is E8H
for (x=0;x<4;x++) {
P2=mydata[x];
sum=sum+mydata[x];
P1=sum;
}
chksumbyte=~sum+1;
P1=chksumbyte;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 171
Checksum 8 bit
Summation: #include <reg51.h>
void main(void) {
25H+ 62H+ 3FH+ 52H = 118H unsigned char mydata[]
Two complements of 118H is ={0x25,0x62,0x3F,0x52,0xE8};
E8H unsigned char shksum=0;
unsigned char x;
Verify the check sum: for (x=0;x<5;x++)
25H+ 62H+ 3FH+ 52H + E8H = 0 chksum=chksum+mydata[x];
if (chksum==0)
P0=‘Good’;
else
P0=‘Bad’;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 172
Bit masking
Bit operators are used for 2 main purposes:
Save memory by storing status flags in one byte
Interface with hardware register
In these 2 cases, it is required the capability of
modifying each bit and check each bit status.
C enables to create macro, which can set, reset (clear)
bit or reverse bit status, named masking
Chapter 4: Data Structures & Algorithms © DIA 2020.2 173
Bit masking
Step 1: Create one integer which represents the status of
each bit or a group of bits
E.g.:
enum {
FIRST = 0x01, /* 0001 binary */
SECND = 0x02, /* 0010 binary */
THIRD = 0x04, /* 0100 binary */
FORTH = 0x08, /* 1000 binary */
ALL = 0x0f /* 1111 binary */
};
Chapter 4: Data Structures & Algorithms © DIA 2020.2 174
Bit masking
In another way:
enum {
FIRST = 1 << 0,
SECND = 1 << 1,
THIRD = 1 << 2,
FORTH = 1 << 3,
ALL = ~(~0 << 4)
};
The last line is used to set/reset a group of bit
1111 1111 /* ~0 */
1111 0000 /* ~0 << 4 */
0000 1111 /* ~(~0 << 4) */
Chapter 4: Data Structures & Algorithms © DIA 2020.2 175
Operations with Bit masking
unsigned flags = 0;
flags |= SECND | THIRD | FORTH; /* (1110). */
flags &= ~(FIRST | THIRD); /* (1010). */
flags ^= (THIRD | FORTH); /* (1100). */
if ((flags & (FIRST | FORTH)) == 0)
flags &= ~ALL; /* (0000). */
Operator | (can be called a pipe ) is used to obtain a combination of bit masks
Operator ~ is used to reverse all the bits (all bits are 1 except the ones with
masks)
Operator |= is used to set bits
Opertor &= is used to reset bits
Opertor ^= is used to flip bits
Opertor & is used to select bits (for checking status).
Chapter 4: Data Structures & Algorithms © DIA 2020.2 176
Macro for each bit
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
#define BitTst(arg,posn) ((arg) & (1L << (posn)))
enum {FIRST, SECND, THIRD};
unsigned flags = 0;
flags = BitSet(flags, FIRST); /* Set first bit. */
flags = BitFlp(flags, THIRD); /* Toggle third bit. */
if (BitTst(flags, SECND) == 0)/* Test second bit. */
flags = 0;
Chapter 4: Data Structures & Algorithms © DIA 2020.2 177
Example
Implement an operation to swap 2 variables using XOR
#define SWAP(a,b) {a^=b; b^=a; a^=b;}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 178
Union revise
Chapter 4: Data Structures & Algorithms © DIA 2020.2 179
Example of Union
Chapter 4: Data Structures & Algorithms © DIA 2020.2 180
Bit Field
Assuming that we have a 32bit register with the above parameters
Chapter 4: Data Structures & Algorithms © DIA 2020.2 181
Bit Field Example
Chapter 4: Data Structures & Algorithms © DIA 2020.2 182
Working with Union
Chapter 4: Data Structures & Algorithms © DIA 2020.2 183
Examples with Union
Chapter 4: Data Structures & Algorithms © DIA 2020.2 184
Portability
Compilers for microcontrollers may consider int as
16bit or 32bit number depending on the
microcontroller
C Compiler may read it:
From left to right
From right to left
Chapter 4: Data Structures & Algorithms © DIA 2020.2 185
Data transfer
Temperature: 25.28 Humidity: 87 Power 111.4W
Chapter 4: Data Structures & Algorithms © DIA 2020.2 186
Sscanf/Sprintf
Chapter 4: Data Structures & Algorithms © DIA 2020.2 187
Example of union usage
Chapter 4: Data Structures & Algorithms © DIA 2020.2 188
Float to IEEE 32bit conversion
(or mantisa)
E.g.:
Chapter 4: Data Structures & Algorithms © DIA 2020.2 189
Float to IEEE 32bit conversion
Chapter 4: Data Structures & Algorithms © DIA 2020.2 190
Convert float to hex and hex to float
Chapter 4: Data Structures & Algorithms © DIA 2020.2 191
4.8 Event-driven programming
Event-driven programming is a programming paradigm
in which the flow of the program is determined by
events such as
Starting the program, initializing variables
Stepping in a loop, waiting for a command or an event
occurring such as mouse clicks, key presses, sensor outputs, or
messages from other programs or threads, timer stop
Event handling subroutines/functions
Getting back to the loop and wait for subsequent
events/commands
Embedded software also follows this paradigm
Chapter 4: Data Structures & Algorithms © DIA 2020.2 192
Example
Read “command” from keyboard and perform
corresponding tasks
Inputs: character from keyboard
a: execute “command A” via function A_handler()
b: execute “command B” via function B_handler()
q: exit the software
Pseudo code of the main loop
Wait for the next command
If a, execute command A
If b, execute command B
If q, exit
Chapter 4: Data Structures & Algorithms © DIA 2020.2 193
Loop control scheme
Repeat until stopping condition matches
Use variable done to verify stopping condition
set done to false
while not done
body statements
if quit command, set done to true
Chapter 4: Data Structures & Algorithms © DIA 2020.2 194
Source code
#define FALSE 0
#define TRUE 1
int main(void) {
char command;
int done;
done = FALSE;
while (!done) {
command = ReadCommand( );
/* Input command from user */
switch (command) {
case ‘a’: A_handler(); /* Execute command A */
break;
case ‘b’: B_handler(); /* Execute command B */
break;
case ‘q’: done = TRUE; /* quit */
break;
default: printf(“Unrecognized command\n”);
}
}
return 0;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 195
Multithreading
Multithreading is a specialized form of multitasking
which allows the computer to run two or more tasks
concurrently
Two types of multitasking:
Process-based multitasking handles the concurrent execution of
programs.
Thread-based multitasking deals with the concurrent execution
of pieces of the same program.
A multithreaded program contains two or more parts
that can run concurrently. Each part of such a program
is called a thread, and each thread defines a separate
path of execution.
Chapter 4: Data Structures & Algorithms © DIA 2020.2 196
Multithreading
Image courtesy: https://en.wikipedia.org/wiki/Thread_(computing)#/media/File:Multithreaded_process.svg
Chapter 4: Data Structures & Algorithms © DIA 2020.2 197
Multithreading
Chapter 4: Data Structures & Algorithms © DIA 2020.2 198
Function call within a thread
1. Using The Function Object
/</em>/ Define the class for function object
class functionObject_class {
// Overload () operator
void operator()(params)
{
// code to be executed
}
};
// Cr
Chapter 4: Data Structures & Algorithms © DIA 2020.2 199
Function call within a thread
2. Using Function Pointer
void funct_call(params){
//code to be executed
}
std::thread thread_obj(funct_call, params);
Chapter 4: Data Structures & Algorithms © DIA 2020.2 200
Function call within a thread
3. Using A Lambda Expression
// Define a lambda expression
auto f = [](params) {
// code for execution
};
std::thread thread_object(f, params);
Chapter 4: Data Structures & Algorithms © DIA 2020.2 201
Example
#include <iostream> int main() {
#include <thread> // Define a Lambda Expression
using namespace std; auto f = [](int n) {
// function to be used in callable for (int i = 0; i < n; i++)
void func_dummy(int N) { cout << "Thread 3 :: callable => lambda
for (int i = 0; i < N; i++) { expression\n";
cout << "Thread 1 :: callable => };
function pointer\n"; //launch thread using function pointer as
} callable
} thread th1(func_dummy, 2);
// A callable object // launch thread using function object as
class thread_obj { callable
public: thread th2(thread_obj(), 2);
void operator()(int n) { //launch thread using lambda expression
for (int i = 0; i < n; i++) as callable
cout << "Thread 2 :: callable => thread th3(f, 2);
function object\n"; // Wait for thread t1 to finish
} th1.join();
}; // Wait for thread t2 to finish
th2.join();
// Wait for thread t3 to finish
th3.join();
return 0;
}
Chapter 4: Data Structures & Algorithms © DIA 2020.2 202
END OF CHAPTER 4
Chapter 4: Data Structures & Algorithms © DIA 2020.2 203