March 1, 2019
For today:
1) Read the sections in Lecture 10 on bitwise operators and unit testing
2) Read Head First C Chapter 5
3) Start Homework 5
4) Work on your project
Today:
1) Homework 4 debrief
2) Passing arrays as parameters
3) Head First C Chapter 5
4) Homework 5 intro
5) Project check ins
For next time:
1) Read Think OS Chapter 6 and do the reading questions
2) Start Homework 5
3) Work on your project
Pull from upstream to get my updated version of strfilter.c, and let's go looking for trouble.
Before:
1) trout.h contains declarations for functions in trout.c and util.c
2) trout.h includes lots of standard libraries
3) main() is in trout.c, which makes the other functions in trout.c hard to reuse
4) trout.c uses lots of global variables
After:
1) trout.h declares the functions in trout.c; utils.h declares the functions in utils.c
2) Each source file includes standard libraries before including trout.h or util.h
3) main() is in main.c, which declares two configuration variables, MAX_TTL and NPROBES.
4) The global variables defined in trout.c are declared extern in trout.h (page 186 of HFC)
What did you have to do to get it to compile cleanly?
Let's finish off the modf exercises from last time.
There are three ways to work with structures in C
1) Static allocation and pass by value
2) Dynamic allocation and pass by pointer
3) Ungodly combinations of (1) and (2)
My advice: always allocate structs dynamically and pass by pointer
Also, always typedef your structs.
AVOID THE FOLLOWING:
struct complex {
float real;
float imag;
};
float mag(struct complex c) {
return ...
}
void main() {
struct complex c;
c.real = 3.0;
c.imag = 4.0;
float m = mag(c);
}
A few problems:
1) The word struct everywhere. It offendeth me.
2) If you pass a statically allocated struct as a parameter, it passes by value; that is, it makes a copy. Same with returning and assigning.
3) If you have both statically-allocated structures and pointers to structures, you will have a mixture of dot notation and arrow notation, and you will make mistakes.
DO THIS INSTEAD
typedef struct {
float real;
float imag;
} Complex;
Complex *make_complex(float real, float imag) {
Complex *c = malloc(sizeof(Complex));
c->real = real;
c->imag = imag;
return c;
}
float mag(Complex *c) {
return ...
}
void main() {
Complex *c = make_complex(3.0, 4.0);
float m = mag(c);
}
Passing by pointer provides consistent semantics that is familiar to Python and Java programmers.
Think in terms of data invariants:
1) Constructor should establish the invariants.
2) All "methods" should maintain the invariants.
3) Non-methods should not modify the fields directly.
4) Provide methods to free compound objects.
Exercise
1) Either pull from upstream or download ExercisesInC/exercises/ex05/shapes.c
2) Follow the instructions at the top of the file: fill in the functions and test them.
3) Draw a stack diagram for main and test_point_in_rect.