Table Of ContentFunctional C
Pieter Hartel Henk Muller
January 3, 1999
i
Functional C
Pieter Hartel Henk Muller
University of Southampton University of Bristol
Revision: 6.7
ii
To Marijke
Pieter
To myfamily and othersources ofinspiration
Henk
Revision: 6.7
(cid:0)c1995,1996PieterHartel&HenkMuller,allrightsreserved.
Preface
The Computer Science Departments of many universities teach a functional lan-
guage as the (cid:2)rst programming language. Using a functional language with its
highlevelofabstractionhelpstoemphasizetheprinciples ofprogramming. Func-
tional programming is only one of the paradigms with which a student should
beacquainted. Imperative, Concurrent, Object-Oriented, and Logic programming
arealso important. Depending on theproblem to besolved, one ofthe paradigms
will bechosen as themost natural paradigmforthat problem.
This book is the course material to teach a second paradigm: imperative pro-
gramming, using C as the programming language. The book has been written so
that it builds on the knowledge that the students have acquired during their (cid:2)rst
course on functional programming, using SML. The prerequisite of this book is
that the principles of programming are already understood; this book does not
speci(cid:2)cally aim to teach‘problemsolving’ or‘programming’. This bookaims to:
Familiarise the reader with imperative programming as another wayof imple-
(cid:1)
menting programs. The aim is to preserve the programming style, that is,
the programmerthinks functionally while implementing an imperative pro-
gram.
(cid:1) Provide understanding of the differences between functionaland imperative pro-
gramming. Functional programming is a high level activity. The ordering of
computations and the allocation of storage are automatic. Imperative pro-
gramming, particularly in C, is a low level activity where the programmer
controlsboththeorderingofcomputationsandtheallocation ofstorage. This
makes imperative programming more dif(cid:2)cult, but it offers the imperative
programmeropportunitiesforoptimisations thatarenotavailabletothefunc-
tional programmer.
Familiarise the reader with the syntax and semantics of ISO-C, especially the
(cid:1)
power of the language (at the same time stressing that power can kill). We
visit alldarkalleysofC,fromvoid *topointerarithmetic andassignments
in expressions. On occasions, we use other languages (like C++ and Pascal)
toillustrate conceptsofimperativelanguagesthatarenotpresentinC.Chas
been chosen because it is a de facto standard for imperative programming,
and becauseits low level naturenicely contrasts withSML. Thosewhowant
to learn, forexample, Modula-2 or Ada-95 afterwardsshould not (cid:2)nd many
dif(cid:2)culties.
iii
iv Preface
(cid:1) Reinforce the principles of programming and problem solving. This is facilitated
by the use of three different languages (mathematics, a functional language,
and an imperative language). The fact that these widely differing languages
havecommon aspectsmakestheidea thatprogrammingprinciples existand
that theyareuseful quite natural.
Reinforce the principle of abstraction. Throughout the book we encourage the
(cid:1)
student to look for more abstract solutions, for example, by viewing the sig-
natureofa function asanabstraction ofits purpose, byusing procedural ab-
stractions (in particular higher order functions) early on, and by using data
abstraction.
Guidethestudentfromspeci(cid:2)cationandmathematicstoimplementationand
(cid:1)
software engineering. In the (cid:2)rst chapters the emphasis is on writing correct
functions and as we make progress the emphasis gradually shifts to trans-
forming correct functions into ef(cid:2)cient and reusable functions. Clean inter-
faces are of paramount importance, and are sacri(cid:2)ced for better ef(cid:2)ciency
only asa last resort.
Each problemin this bookis solved in threesteps:
Aspeci(cid:2)cation ofthe problemis made.
(cid:1)
Anappropriate algorithm is found to deliver solutions that satisfy the speci-
(cid:1)
(cid:2)cation.
Thealgorithmisimplementedasef(cid:2)cientlyaspossible. Throughoutthebook,
(cid:1)
theemphasis is on this third step.
The language of mathematics is used to specify the problems. This includes the
basics of set theory and logic. The student should have some familiarity with the
calculi of sets, predicate logic, and propositional logic. This material is taught at
most universities during a(cid:2)rst courseon discrete mathematics orformallogic.
The appropriate algorithm is given in SML. SML is freelyavailable for a range
ofplatforms(PC’s,UNIXworkstations, Apple),andisthereforepopularasateach-
ing language. As many functional languages are not too different from SML, an
appendixgivesabriefreviewofSMLforthosefamiliarwithanyoftheothermain
streamfunctional languages,such as Miranda, Haskell, Clean, orScheme.
As the target language to implement solutions in an imperative style we have
chosen C. The choice to use C and not C++ was a dif(cid:2)cult one. Both languages
aremainstreamlanguages,andwouldthereforebesuitable asthetargetlanguage.
We havechosen C becauseit moreclearly exposes thelow level programming. To
illustratethisconsiderthemechanismsthatthelanguagesprovideforcallbyrefer-
ence. In C, arguments must be explicitly passed as a pointer. Thecaller must pass
the address, the callee must dereference the pointer. This in contrast with the call by
reference mechanism of C++ (and Pascal and Modula-2). This explicit call by ref-
erenceis adidactical assetasit clearly exposesthemodel behindcall byreference,
and its dangers(in theformofunwanted aliases).
Revision: 6.8
Preface v
Asthisbookisintended tobeusedina(cid:2)rstyearcourse,onlyfewassumptions
were made about prior knowledge of the students. Reasoning about the correct-
ness of programsrequires proof skills, which students might not have acquired at
this stage. Therefore we have con(cid:2)ned all proofs to specially marked exercises.
Todistinguish theprogrammingexercisesfromtheexercisesrequiringaproof,we
have marked the latter with an asterisk. We are con(cid:2)dent that the book can be
usedwithoutmakingasingleproof. Howeverwewouldrecommendthestudents
to go through the proofs on a second reading. The answersto one third of the ex-
ercises areprovided inAppendix A.
The student should have an understanding of the basic principles of comput-
ing. This would include base 2 arithmetic and the principles of operation of the
von Neumann machine. A computer appreciation course would be most appro-
priatetocoverthis material. Thebookcontainsexamplesfromotherareasofcom-
puter science, including data bases, computer graphics, the theory of program-
ming languages, and computer architecture. These examples can be understood
without prior knowledgeofthese areas.
Acknowledgements
ThehelpandcommentsofHughGlaser,AndyGravell,LauraLafave,DenisNicole,
Peter Sestoft, and the anonymous referees have been important to us. The mate-
rial ofthe bookhasundergoneits (cid:2)rsttest in Southamptonin 1995/1996. The(cid:2)rst
year Computer Science students of 1995, and in particular Jason Datt and Alex
Walkerhave givenus alot ofusefulfeedback.
We have used a number of public domain software tools in the development
of the book. The noweb literate programming tools of Norman Ramsey, the rail
roaddiagrammingtoolsfromL.Rooijakkers,gpicbyBrianKernighan,TEX,LATEX,
NewJerseySML, and theGnu C compiler wereparticularly useful.
Revision: 6.8
vi Preface
Revision: 6.8
(cid:0)c1995,1996PieterHartel&HenkMuller,allrightsreserved.
Contents
Preface iii
1 Introduction 1
1.1 Thefunctional andthe imperative paradigms . . . . . . . . . . . . . . 1
1.1.1 Theadvantageofstate . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.2 Theadvantageofpurefunctions . . . . . . . . . . . . . . . . . 3
1.1.3 Idiomatic building blocks in C . . . . . . . . . . . . . . . . . . 3
1.2 Guide tothe book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Functionsand numbers 7
2.1 Amodel ofcomputation . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1.1 Acomputational model forSML programs . . . . . . . . . . . 8
2.1.2 Acomputational model forC programs . . . . . . . . . . . . . 9
2.1.3 Compiling and executingaC program . . . . . . . . . . . . . 10
2.2 Elementary functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.2.1 TheheaderofaC function, typesand identi(cid:2)ers . . . . . . . . 14
2.2.2 ThebodyofaC function and its behaviour . . . . . . . . . . . 15
2.2.3 Theexecutionof aC program . . . . . . . . . . . . . . . . . . . 17
2.2.4 Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.2.5 Logical operators . . . . . . . . . . . . . . . . . . . . . . . . . . 19
2.2.6 De(cid:2)ningatypeforBooleans, typedefand enum . . . . . . . 20
2.3 Characters, patternmatching, partial functions . . . . . . . . . . . . . 21
2.3.1 Implementingpattern matching in C . . . . . . . . . . . . . . . 22
2.3.2 Partial functions . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.3.3 Differencesand similarities betweencharactersand integers . 27
2.4 Real numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
2.4.1 Coercions ofintegers and (cid:3)oating point numbers . . . . . . . 32
2.5 Functions asarguments . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.5.1 Sums . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.5.2 Products . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
2.5.3 Anextended exampleofhigherorder functions: bisection . . 39
2.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.7 Furtherexercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
vii
viii CONTENTS
3 Loops 51
3.1 Amodel ofthe store . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.2 Local variabledeclarations and assignments . . . . . . . . . . . . . . 53
3.3 While loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
3.3.1 Single argumenttail recursion . . . . . . . . . . . . . . . . . . 61
3.3.2 Multiple argumenttail recursion . . . . . . . . . . . . . . . . . 64
3.3.3 Non-tail recursion: factorial . . . . . . . . . . . . . . . . . . . . 68
3.3.4 Moreon assignments . . . . . . . . . . . . . . . . . . . . . . . . 73
3.3.5 Breakingout ofwhile-loops . . . . . . . . . . . . . . . . . . . . 75
3.4 Forloops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.4.1 Factorial using afor-loop . . . . . . . . . . . . . . . . . . . . . 83
3.4.2 Folding fromthe right . . . . . . . . . . . . . . . . . . . . . . . 86
3.5 Generalizing loops andcontrol structures . . . . . . . . . . . . . . . . 88
3.5.1 Combining foldlwithmap: sum ofsquares . . . . . . . . . . 89
3.5.2 Combining foldlwithfilter: perfectnumbers . . . . . . . 91
3.5.3 Nested forstatements . . . . . . . . . . . . . . . . . . . . . . . 95
3.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.7 Furtherexercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
4 Structs and Unions 101
4.1 Structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4.2 Structs in structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.3 Unions in structs: algebraic data types . . . . . . . . . . . . . . . . . . 105
4.3.1 Union types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.3.2 Patternmatching: theswitch statement . . . . . . . . . . . . . 108
4.3.3 Algebraictypesin otherimperative languages . . . . . . . . . 110
4.4 Pointers: referencesto values . . . . . . . . . . . . . . . . . . . . . . . 112
4.4.1 De(cid:2)ningpointers . . . . . . . . . . . . . . . . . . . . . . . . . . 112
4.4.2 Assignments throughpointers . . . . . . . . . . . . . . . . . . 114
4.4.3 Passing argumentsbyreference. . . . . . . . . . . . . . . . . . 116
4.4.4 Lifetime ofpointers and storage . . . . . . . . . . . . . . . . . 119
4.5 Void pointers: partial application . . . . . . . . . . . . . . . . . . . . . 120
4.5.1 Thedangerofexplicit typecasts . . . . . . . . . . . . . . . . . 125
4.5.2 Void pointers andparametric polymorphism . . . . . . . . . . 126
4.6 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
4.7 Furtherexercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
5 Arrays 133
5.1 Sequences asamodel oflinear data structures . . . . . . . . . . . . . 134
5.1.1 Thelengthofa sequence . . . . . . . . . . . . . . . . . . . . . . 134
5.1.2 Accessingan element ofasequence . . . . . . . . . . . . . . . 134
5.1.3 Updating anelement ofasequence . . . . . . . . . . . . . . . 135
5.1.4 Theconcatenation oftwo sequences . . . . . . . . . . . . . . . 135
5.1.5 Thesubsequence . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.2 Sequences asarraysinSML . . . . . . . . . . . . . . . . . . . . . . . . 136
5.2.1 Creatingan SML array . . . . . . . . . . . . . . . . . . . . . . . 136
Revision: 6.8
CONTENTS ix
5.2.2 Thelengthofan SML array . . . . . . . . . . . . . . . . . . . . 137
5.2.3 Accessingan element ofanSML array . . . . . . . . . . . . . . 137
5.2.4 Updating anelement ofanSML array . . . . . . . . . . . . . . 137
5.2.5 Destructiveupdates in SML . . . . . . . . . . . . . . . . . . . . 138
5.3 Sequences asarraysinC . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.3.1 DeclaringaC array . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.3.2 Accessingan element ofaC array . . . . . . . . . . . . . . . . 139
5.4 Basic arrayoperations : Arithmetic mean . . . . . . . . . . . . . . . . 139
5.5 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142
5.5.1 Comparingstrings . . . . . . . . . . . . . . . . . . . . . . . . . 143
5.5.2 Returningstrings; morepropertiesof arrays . . . . . . . . . . 144
5.5.3 Anapplication ofarraysand strings: argcand argv . . . . . 146
5.6 Manipulating arraybounds, boundchecks . . . . . . . . . . . . . . . 147
5.7 Dynamicmemory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.7.1 Theallocation ofdynamic arrays . . . . . . . . . . . . . . . . . 153
5.7.2 Theextensionof dynamic arrays . . . . . . . . . . . . . . . . . 155
5.7.3 Thedeallocation of dynamic arrays . . . . . . . . . . . . . . . 159
5.7.4 Explicit versusimplicit memorymanagement . . . . . . . . . 161
5.7.5 Ef(cid:2)ciency aspectsof dynamic memory . . . . . . . . . . . . . 162
5.8 Slicing arrays: pointer arithmetic . . . . . . . . . . . . . . . . . . . . . 163
5.9 Combining arraysand structures . . . . . . . . . . . . . . . . . . . . . 168
5.10 Multi-dimensional arrayswith (cid:2)xedbounds . . . . . . . . . . . . . . 174
5.11 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
5.12 Furtherexercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176
6 Lists 181
6.1 Lists ofcharacters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6.1.1 List access functions: head andtail . . . . . . . . . . . . . . . . 183
6.2 Thelength ofalist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
6.3 Accessing anarbitraryelementof alist . . . . . . . . . . . . . . . . . . 186
6.4 Append, (cid:2)lter and map: recursiveversions . . . . . . . . . . . . . . . 186
6.4.1 Appendingtwo lists . . . . . . . . . . . . . . . . . . . . . . . . 186
6.4.2 Filtering elements fromalist . . . . . . . . . . . . . . . . . . . 188
6.4.3 Mappinga function overalist . . . . . . . . . . . . . . . . . . 190
6.5 Open lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
6.5.1 Openlists byrememberingthelast cell . . . . . . . . . . . . . 193
6.5.2 Openlists byusingpointers to pointers . . . . . . . . . . . . . 195
6.5.3 Appendusing openlists . . . . . . . . . . . . . . . . . . . . . . 197
6.6 Lists versus arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
6.6.1 Converting anarrayto a list . . . . . . . . . . . . . . . . . . . . 199
6.6.2 Fromalist to anarray . . . . . . . . . . . . . . . . . . . . . . . 201
6.7 Variable numberofarguments . . . . . . . . . . . . . . . . . . . . . . 204
6.8 Store reuse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
6.9 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
6.10 Furtherexercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
Revision: 6.8