You are on page 1of 341

C Programming Tutorial (K&R version 4)

This is a C Programming Tutorial for people who have a little experience with an interpreted programming language, such as Emacs Lisp or a GNU shell. Edition .!" Cop#right $ %&'(,%&&& )ar* +urgess Permission is granted to ma*e and distri,ute ver,atim copies of this manual provided the cop#right notice and this permission notice are preserved on all copies.

Preface.ntroduction/eserved words 0 example1perating s#stemsLi,rariesProgramming st#le2orm of a C programComments2unctions3aria,lesParameters4copePreprocessorPointers4tandard 1utput and 4tandard .nput5ssignments Expressions and 1perators6ecisionsLoops5rra#s4tringsPutting together a program4pecial Li,rar# 2unctions and )acros7idden 1perators)ore on 6ata T#pes)achine Level 1perations2iles and 6evices4tructures and Unions6ata structures/ecursionExample Programs chapterErrors and de,ugging4ummar#reserved words listComparisons Character Conversion Ta,leEmacs st#le file5nswers to 8uestions.ndex-

Preface
Ever# program is limited ,# the language which is used to write it. C is a programmer9s language. Unli*e +54.C or Pascal, C was not written as a teaching aid, ,ut as an implementation language. C is a computer language and a programming tool which has grown popular ,ecause programmers li*e it: .t is a tric*# language ,ut a masterful one. 4ceptics have said that it is a language in which ever#thing which can go wrong does go wrong. True, it does not do much hand holding, ,ut also it does not hold an#thing ,ac*. .f #ou have come to C in the hope of finding a powerful language for writing ever#da# computer programs, then #ou will not ,e disappointed. C is ideall# suited to modern computers and modern programming. This ,oo* is a tutorial. .ts aim is to teach C to a ,eginner, ,ut with enough of the details so as not ,e outgrown as the #ears go ,#. .t presumes that #ou have some previous a8uaintance with programming ;; #ou need to *now what a varia,le is and what a function is ;; ,ut #ou do not need much experience. .t is not essential to follow the order of the chapters rigorousl#, ,ut if #ou are a ,eginner to C it is recommended. <hen it comes down to it, most languages have ,asicall# the same *inds of features- varia,les, wa#s of ma*ing loops, wa#s of ma*ing decisions, wa#s of accessing files etc. .f #ou want to plan #our assault on C, thin* a,out what #ou alread# *now a,out programming and what #ou expect to loo* for in C. =ou will most li*el# find all of those things and more, as #ou wor* though the chapters. The examples programs range from 8uic* one;function programs, which do no more than illustrate the sole use of one simple feature, to complete application examples occup#ing several pages. .n places these examples ma*e use of features ,efore the# have properl# ,een explained. These programs serve as a taster of what is to come.

Mark Burgess. 1987, 1999

This book was first written in 1987; this new edition was updated and rewritten in 1999. The book was originally published by Dabs Press. Since the book has gone out of print Da!id "therton of Dabs and # agreed to release the $anuscript as per the original contract. This new edition is written in Te%info which is a docu$entation syste$ that uses a single source file to produce both on&line infor$ation and printed output. 'ou can read this tutorial online using either the ($acs #nfo reader the standalone #nfo reader or a )orld )ide )eb browser or you can read this sa$e te%t as a typeset printed book.

Introduction
)hat is *+ )hat is it for+ )hy is it special+

Levels+asic ideasThe compilerErrorsUse of Upper and Lower Case>uestions %-

High Levels and Low Levels


5n# *ind of o,?ect that is sufficientl# complicated can ,e thought of as having levels of detail@ the amount of detail we see depends upon how closel# we scrutiniAe it. 5 computer falls definitel# into the categor# of complex o,?ects and it can ,e thought of as wor*ing at man# different levels. The terms low le!el and high le!el are often used to descri,e these onion;la#ers of complexit# in computers. Low level is perhaps the easiest to understand- it descri,es a level of detail which is ,uried down amongst the wor*ing parts of the machine- the low level is the level at which the computer seems most primitive and machine;li*e. 5 higher level descri,es the same o,?ect, ,ut with the detail left out. .magine stepping ,ac* from the complexit# of the machine level pieces and grouping together parts which wor* together, then covering up all the details. B2or instance, in a car, a group of nuts, ,olts, pistons can ,e grouped together to ma*e up a new ,asic o,?ect- an engine.C 5t a high level a computer ,ecomes a group of ,lac* ,oxes which can then ,e thought of as the ,asic components of the computer. C is called a high level, compiler language. The aim of an# high level computer language is to provide an eas# and natural wa# of giving a programme of instructions to a computer Ba computer programC. The language of the raw computer is a stream of num,ers called machine code. 5s #ou might expect, the action which results from a single machine code instruction is ver# primitive and man# thousands of them are re8uired to ma*e a program which does an#thing su,stantial. .t is therefore the ?o, of a high level language to provide a new set of ,lac* ,ox instructions, which can ,e given to the computer without us needing to see what happens inside them ; and it is the ?o, of a compiler to fill in the details of these D,lac* ,oxesD so that the final product is a se8uence of instructions in the language of the computer.

C is one of a large num,er of high level languages which can ,e used for general purpose programming, that is, an#thing from writing small programs for personal amusement to writing complex applications. .t is unusual in several wa#s. +efore C, high level languages were criticiAed ,# machine code programmers ,ecause the# shielded the user from the wor*ing details of the computer, with their ,lac* ,ox approach, to such an extent that the languages ,ecome inflexi,le- in other words, the# did not allow programmers to use all the facilities which the machine has to offer. C, on the other hand, was designed to give access to an# level of the machine down to raw machine code and ,ecause of this it is perhaps the most flexi,le of all high level languages.

4urprisingl#, programming ,oo*s often ignore an important role of high level languageshigh level programs are not onl# a wa# to express instructions to the computer, the# are also a means of communication among human ,eings. The# are not merel# monologues to the machine, the# are a wa# to express ideas and a wa# to solve pro,lems. The C language has ,een e8uipped with features that allow programs to ,e organiAed in an eas# and logical wa#. This is vitall# important for writing length# programs ,ecause complex pro,lems are onl# managea,le with a clear organiAation and program structure. C allows meaningful varia,le names and meaningful function names to ,e used in programs without an# loss of efficienc# and it gives a complete freedom of st#le@ it has a set of ver# flexi,le loop constructions Bfor, while, doC and neat wa#s of ma*ing decisions. These

provide an excellent ,asis for controlling the flow of programs.

5nother unusual feature of C is the wa# it can express ideas concisel#. The richness of a language shapes what it can tal* a,out. C gives us the apparatus to ,uild neat and compact programs. This sounds, first of all, either li*e a great ,onus or something a ,it suspect. .ts conciseness can ,e a mixed ,lessing- the aim is to tr# to see* a ,alance ,etween the often conflicting interests of reada,ilit# of programs and their conciseness. +ecause this side of programming is so often presumed to ,e understood, we shall tr# to develop a st#le which finds the right ,alance. C allows things which are disallowed in other languages- this is no defect, ,ut a ver# powerful freedom which, when used with caution, opens up possi,ilities enormousl#. .t does mean however that there are aspects of C which can run awa# with themselves unless some care is ta*en. The programmer carries an extra responsi,ilit# to write a careful and thoughtful program. The reward for this care is that fast, efficient programs can ,e produced. C tries to ma*e the ,est of a computer ,# lin*ing as closel# as possi,le to the local environment. .t is no longer necessar# to have to put up with hopelessl# inade8uate inputEoutput facilities an#more Ba legac# of the timesharingEmainframe computer eraCone can use ever#thing that a computer has to offer. 5,ove all it is flexi,le. Clearl# no language can guarantee intrinsicall# good programs- there is alwa#s a responsi,ilit# on the programmer, personall#, to ensure that a program is neat, logical and well organiAed, ,ut it can give a framewor* in which it is eas# to do so.

The aim of this ,oo* is to conve# some of the C philosoph# in a practical wa# and to provide a comprehensive introduction to the language ,# appealing to a num,er of examples and ,# stic*ing to a strict structuring scheme. .t is hoped that this will give a flavour of the *ind of programming which C encourages.

Basic ideas a out !


)hat to do with a co$piler. )hat can go wrong. Using a compiler language is not the same as using an interpreted language li*e +54.C or a GNU shell. .t differs in a num,er of wa#s. To ,egin with, a C program has to ,e created in two stages

2irstl#, the program is written in the form of a num,er of text files using a screen editor. This form of the program is called the source progra$. .t is not possi,le to execute this file directl#. 4econdl#, the completed source file is passed to a compiler;;a program which generates a new file containing a machine code translation of the source text. This file is called an o,?ect file or executa,le file. The executa,le file is said to have ,een compiled from the source text.

Compiler languages do not usuall# contain their own editor, nor do the# have words li*e RUN with which to execute a finished program. =ou use a screen editor to create the words of a program Bprogram textC and run the final program in its compiled form usuall# ,# simpl# t#ping the name of the executa,le file.

The compilerErrors-

"he !o#$iler
5 C program is made ,# running a co$piler which ta*es the t#ped source program and converts it into an o,?ect file that the computer can execute. 5 compiler usuall# operates in two or more phases Band each phase ma# have stages within itC. These phases must ,e executed one after the other. 5s we shall see later, this approach provides a flexi,le wa#

of compiling programs which are split into man# files.

5 two;phase compiler wor*s in the following wa#

Phase % scans a source program, perhaps generating an intermediate code B8uadruples or pcodeC which helps to simplif# the grammar of the language for su,se8uent processing. .t then converts the intermediate code into a file of o,?ect code Bthough this is usuall# not executa,le #etC. 5 separate o,?ect file is ,uilt for each separate source file. .n the GNU C compiler, these two stages are run with the command gcc -c@ the output is one or more .o files. Phase " is a Lin*er. This program appends standard li,rar# code to the o,?ect file so that the code is complete and can Dstand aloneD. 5 C compiler lin*er suffers the slightl# arduous tas* of lin*ing together all the functions in the C program. Even at this stage, the compiler can fail, if it finds that it has a reference to a function which does not exist. <ith the GNU C compiler this stage is activated ,# the command gcc -o or ld.

To avoid the irritation of t#ping two or three separate commands Bwhich are often cum,ersomeC #ou will normall# find a simple interface for executing compiler. Traditionall# this is an executa,le program called cc for C Compilercc filename gcc filename

1n GNU s#stems, this results in the creation of an executa,le program with the default name a.out. To tell the compiler what #ou would li*e the executa,le program to ,e called, use the -o option for setting the name of the o,?ect codegcc -o program-name filname

2or example, to create a program called myprog from a file called myprog.c, write
gcc -o myprog myprog.c

%rrors
Errors are mista*es which we the programmers ma*e. There are different *inds of errorSynta% Errors in the s#ntax, or word structure of a program are caught ,efore #ou run it, at compilation time ,# the compiler program. The# are listed all in one go, with the line num,er, in the text file, at which the error occurred and a message to sa# what was wrong. 2or example, suppose #ou write sin (x) y = ; in a program instead of y = sin (x);, which assigns the value of the sin of x to y. Upon compilation, #ou would see this error messageeg.c: n function !main": eg.c:#$: parse error %efore !y"

B.f #ou compile the program in Emacs, #ou can ?ump directl# to the error.C 5 program with s#ntax errors will cause a compiler program to stop tr#ing to generate machine code and will not create an executa,le. 7owever, a compiler will usuall# not stop at the first error it encounters ,ut will attempt to continue chec*ing the s#ntax of a program right to the last line ,efore a,orting, and it is common to su,mit a program for compilation onl# to receive a long and ungratif#ing list of errors from the compiler. .t is a shoc* to ever#one using a compiler for the first time how a single error can throw the compiler off course and result in a huge and confusing list of non; existent errors, following a single true culprit. The situation thus loo*s much worse than it reall# is. =ou9ll get used to this with experience, ,ut it can ,e ver# disheartening. 5s a rule, loo* for the first error, fix that, and then recompile. 1f course, after #ou have ,ecome experienced, #ou will recogniAe when su,se8uent error messages are due to independent pro,lems and when the# are due to a cascade. +ut at the ,eginning, ?ust loo* for and fix the first error. #ntention Errors in goal or purpose Blogical errorsC occur when #ou write a program that wor*s, ,ut does not do what #ou intend it to do. =ou intend to send a letter to all drivers whose licenses will expire soon@ instead, #ou send a letter to all drivers whose licenses will expire sometime. .f the compilation of a program is successful, then a new file is created. This file will contain machine code which can ,e executed according to the rules of the computer9s local operating s#stem.

<hen a programmer wants to ma*e alterations and corrections to a C program, these have to ,e made in the source text file itself using an editor@ the program, or the salient parts, must then ,e recompiled.

&se of &$$er and Lower !ase


1ne of the reasons wh# the compiler can fail to produce the executa,le file for a program is #ou have mist#ped something, even through the careless use of upper and lower case characters. The C language is case dependent. Unli*e languages such as Pascal and some versions of +54.C, the C compiler distinguishes ,etween small letters and capital letters. This is a potential source of 8uite trivial errors which can ,e difficult to spot. .f a letter is t#ped in the wrong case, the compiler will complain and it will not produce an executa,le program.

'eclarations
Compiler languages re8uire us to ma*e a list of the names and t#pes of all varia,les which are going to ,e used in a program and provide information a,out where the# are going to ,e used. This is called declaring varia,les. .t serves two purposes- firstl#, it provides the compiler with a definitive list of the varia,les, ena,ling it to cross chec* for errors, and secondl#, it informs the compiler how much space must ,e reserved for each varia,le when the program is run. C supports a variet# of varia,le t#pes Bvaria,les which hold different *inds of dataC and allows one t#pe to ,e converted into another. Conse8uentl#, the t#pe of a varia,le is of great importance to the compiler. .f #ou fail to declare a varia,le, or declare it to ,e the wrong t#pe, #ou will see a compilation error.

(uestions
%. ". G. . H. <hat is a compilerF 7ow is a C program runF 7ow is a C program compiled usuall#F 5re upper and lower case e8uivalent in CF <hat the two different *inds of error which can ,e in a programF

)eserved words and an e*a#$le


C programs are constructed from a set of reserved words which provide control and from li,raries which perform special functions. The ,asic instructions are ,uilt up using a reserved set of words, such as main, for, if,while, default, dou%le, extern, for, and int, to name ?ust a few. These words ma# not ,e used in ?ust an# old wa#- C demands that the# are used onl# for giving commands or ma*ing statements. =ou cannot use default, for example, as the name of a varia,le. 5n attempt to do so will result in a compilation error. 4ee 5ll the /eserved <ords, for a complete list of the reserverd words.

<ords used in included li,aries are also, effectivel#, reserved. .f #ou use a word which has alread# ,een adopted in a li,rar#, there will ,e a conflict ,etween #our choice and the li,rar#. Li,raries provide fre,uently used functionality and, in practice, at least one li,rar# must ,e included in ever# program- the so;called C li,rar#, of standard functions. 2or example, the stdio li,rar#, which is part of the C li,rar#, provides standard facilities for input to and output from a program. .n fact, most of the facilities which C offers are provided as li,raries that are included in programs as plug;in expansion units. <hile the features provided ,# li,raries are not strictl# a part of the C language itself, the# are essential and #ou will never find a version of C without them. 5fter a li,rar# has ,een included in a program, its functions are defined and #ou cannot use their names.

printfExample %1utput %>uestions "-

"he printf() function


1ne invalua,le function provided ,# the standard inputEoutput li,rar# is called printf or Iprint;formatted9. .t provides an super,l# versatile wa# of printing text. The simplest wa# to use it is to print out a literal stringprintf (&..some string...&);

Text is eas#, ,ut we also want to ,e a,le to print out the contents of varia,les. These can ,e inserted into a text string ,# using a Icontrol se8uence9 inside the 8uotes and listing the varia,les after the string which get inserted into the string in place of the control se,uence. To print out an integer, the control se8uence 'd is usedprintf (& nteger = 'd&(someinteger);

The varia,le someinteger is printed instead of 'd. The printf function is descri,ed in full detail in the relevant chapter, ,ut we9ll need it in man# places ,efore that. The example program ,elow is a complete program. .f #ou are reading this in .nfo, #ou can cop# this to a file, compile and execute it.

%*a#$le Listing
)***********************************************************) )* +hort ,oem *) )***********************************************************) -include .stdio.h/ )***********************************************************)

main () 0 printf printf printf printf printf printf printf printf printf printf printf printf A

)* ,oem *) (&1stronomy is 'dderful 2n&(#); (&1nd interesting 'd 2n&($); (&3he ear'd 4ol4es around the sun 2n&(5); (&1nd ma6es a year 'd you 2n&(7); (&3he moon affects the sur 'd heard 2n&(8); (&9y law of phy'd great 2n&(:); (& t 'd when the the stars so %right 2n&(;); (&<o nightly scintill'd 2n&(=); (& f watchful pro4idence %e'd 2n&(>); (&?ith good intentions fraught 2n&); (&+hould not 6eep up her watch di4ine 2n&); (&?e soon should come to 'd 2n&(@);

+ut$ut
1stronomy is #derful 2n& 1nd interesting $ 3he ear5 4ol4es around the sun 1nd ma6es a year 7 you 3he moon affects the sur 8 heard 9y law of phy:d great t ; when the the stars so %right <o nightly scintill= f watchful pro4idence %e> ?ith good intentions fraught +hould not 6eep up her watch di4ine ?e soon should come to @

(uestions
%. ". G. . <rite a command to print out the message D<ow ,ig dealD. <rite a command to print out the num,er ""F <rite two commands to print out DThe G <ise )enD two different wa#s. <h# are there onl# a few reserved command words in CF

+$erating s,ste#s and environ#ents


)here is a * progra$ born+ -ow is it created+ The ,asic control of a computer rests with its operating s#stem. This is a la#er of software which drives the hardware and provides users with a comforta,le environment in which to wor*. 5n operating s#stem has two main components which are of interest to users- a user interface Boften a command languageC and a filing syste$. The operating s#stem is the route to all input and output, whether it ,e to a screen or to files on a dis*. 5 programming language has to get at this input and output easil# so that programs can

send out and receive messages from the user and it has to ,e in contact with the operating s#stem in order to do this. .n C the lin* ,etween these two is ver# efficient. 1perating s#stems var# widel# ,ut most have a command language or shell which can ,e used to t#pe in commands. /ecentl# the tendenc# has ,een to tr# to eliminate t#ping completel# ,# providing graphical user interfaces BGU.sC for ever# purpose. GU.s are good for carr#ing out simple procedures li*e editing, ,ut the# are not well suited to giving complicated instructions to a computer. 2or that one needs a command language. .n the networ* version of this ,oo* we shall concentrate on Unix shell commands since the# are the most important to programmers. 1n microcomputers command languages are usuall# ver# similar in concept, though more primitive, with onl# slightl# different words for essentiall# the same commands. BThis is a slightl# superficial viewC. <hen most compiler languages were developed, the# were intended to ,e run on large mainframe computers which operated on a multi;user, time;sharing principle and were incapa,le of interactive communication with the user. )an# compiler languages still have this inade8uac# when carried over to modern computers, ,ut C is an exception, ,ecause of its uni8ue design. .nput and output are not actuall# defined as a fixed, unchanging part of the C language. .nstead there is a standard file which has to ,e included in programs and defines the inputEoutput commands that are supported ,# the language for a particular computer and operating s#stem. This file is called a standard C li,rar#. B4ee the next chapter for more information.C The li,rar# is standard in the sense that C has developed a set of functions which all computers and operating s#stems must implement, ,ut which are speciall# adapted to #our s#stem.

2iles devices2ilenamesCommand languages>uestions G-

-iles and 'evices


The filing s#stem is also a part of inputEoutput. .n man# operating s#stems all routes in and out of the computer are treated ,# the operating s#stem as though the# were files or data strea$s Beven the *e#,oard:C. C does this implicitl# Bit comes from UnixC. The file from which C normall# gets its input from is called stdin or standard input file and it is usuall# the *e#,oard. The corresponding route for output is called DstdoutD or standard output file and is usuall# a monitor screen. +oth of these are parts of stdio or standard input output. The *e#,oard and the monitor screen are not reall# files, of course, the# are Idevices9, Bit is not possi,le to re;read what has ,een sent to the monitorD, or write to the *e#,oard.C, ,ut devices are represented ,# files with special names, so that the *e#,oard is treated as a read;onl# file, the monitor as a write onl# file... The advantage of treating devices li*e this is that it is not necessar# to *now how a particular device wor*s, onl# that it exists somewhere, connected to the computer, and can ,e written to or read from. .n other words, it is exactl# the same to read or write from a device as it is to read or write from a file. This is a great simplification of inputEoutput: The filenames of devices Boften given the loft# title Ipseudo device names9C depend upon #our particular operating s#stem. 2or instance, the printer might ,e called DP/ND or DP/TD. =ou might have to

open it explicitl# as a file. <hen input is ta*en solel# from the *e#,oard and output is alwa#s to the screen then these details can ?ust ,e forgotten.

-ilena#es
The compiler uses a special convention for the file names, so that we do not confuse their contents. The name of a source program Bthe code which #ou writeC is filename.c. The compiler generates a file of o,?ect code from this called filename.o, as #et unlin*ed. The final program, when lin*ed to li,raries is called filename on Unix;li*e operating s#stems, and filename.BCB on <indows derived s#stems. The li,raries themselves are also files of o,?ect code, t#picall# called li%libraryname.a or li%libraryname.so. 7eader files are alwa#s called libname.h. The endings Idot something9 Bcalled file extensionsC identif# the contents of files for the compiler. The dotted endings mean that the compiler can generate an executa,le file with the same name as the original source ; ?ust a different ending. The 8uad file and the o,?ect file are onl# wor*ing files and should ,e deleted ,# the compiler at the end of compilation. The .c suffix is to tell the compiler that the file contains a C source program and similarl# the other letters indicate non;source files in a convenient wa#. To execute the compiler #ou t#pe,
cc filename

2or example,
cc foo.c

!o##and Languages and !onsoles


.n order to do an#thing with a compiler or an editor #ou need to *now a little a,out the command language of the operating s#stem. This means the instructions which can ,e given to the s#stem itself rather than the words which ma*e up a C program. e.g.
ls -l less filename emacs filename

.n a large operating s#stem Bor even a relativel# small oneC it can ,e a ma?or feat of recollection to *now all of the commands. 2ortunatel# it is possi,le to get ,# with *nowing ?ust handful of the most common ones and having the s#stem manual around to leaf through when necessar#. 5nother important o,?ect is the Ipanic ,utton9 or program interruption *e#. Ever# s#stem will have its own wa# of halting or terminating the operation of a program or the execution of a command. Commonl# this will involve two simultaneous *e# presses, such as D3RE D, D3RE F or D3RE-< etc. .n GNUELinux, D3RE-D is used.

(uestions
%. <hat is an operating s#stem forF ". <hat is a pseudo;device nameF G. .f #ou had a C source program which #ou wanted to call Iaccounts9 what name would #ou save it underF . <hat would ,e the name of the file produced ,# the compiler of the program in GF H. 7ow would this program ,e runF

Li raries
Plug&in * e%pansions. -eader files. The core of the C language is small and simple. 4pecial functionalit# is provided in the form of li,raries of read#;made functions. This is what ma*es C so porta,le. 4ome li,raries are provided for #ou, giving #ou access to man# special a,ilities without needing to reinvent the wheel. =ou can also ma*e #our own, ,ut to do so #ou need to *now how #our operating s#stem ,uilds li,raries. <e shall return to this later. Li,raries are files of read#;compiled code which we can merge with a C program at compilation time. Each li,rar# comes with a num,er of associated header files which ma*e the functions easier to use. 2or example, there are li,raries of mathematical functions, string handling functions and inputEoutput functions and graphics li,raries. .t is up to ever# programmer to ma*e sure that li,raries are added at compilation time ,# t#ping an optional string to the compiler. 2or example, to merge with the math li,rar# li%m.a #ou would t#pe
cc -o program_name prog.c -lm

when #ou compile the program. The -lm means- add in li%m. .f we wanted to add in the soc*et li,rar# li%soc6et.a to do some networ* programming as well, we would t#pe
cc -o program_name prog.c -lm -lsoc6et

and so on. <h# are these li,raries not ?ust included automaticall#F +ecause it would ,e a waste for the compiler to add on lots of code for maths functions, sa#, if the# weren9t needed. <hen li,rar# functions are used in programs, the appropriate li,rar# code is included ,# the compiler, ma*ing the resulting o,?ect code often much longer.

Li,raries are supplemented ,# header files which define $acros, data types and e%ternal data to ,e used in con?unction with the li,raries. 1nce a header file has ,een included, it has effectivel# added to the list of reserved words and commands in the language. =ou cannot then use the names of functions or macros which have alread# ,een defined in li,raries or header files to mean an#thing other than what the li,rar# specifies. The most commonl# used header file is the standard inputEoutput li,rar# which is called stdio.h. This ,elongs to a su,set of the standard C li,rar# which deals with file handling. The math.h header file ,elongs to the mathematics li,rar# li%m.a. 7eader files for li,raries are included ,# adding to the source code-include header.h

at the top of a program file. 2or instance-include &myheader.h&

includes a personal header file which is in the current director#. 1r


-include .stdio.h/

includes a file which lies in a standard director# li*e )usr)include. The -include directive is actuall# a command to the C preprocessor, which is dealt with more full# later, 4ee Preprocessor. 4ome functions can ,e used without having to include li,rar# files or special li,raries explicitl# since ever# program is alwa#s merged with the standard * library, which is called li%c.
-include .stdio.h/ main () 0 printf (&D standard )G file is included2n&); printf (&Hello worldI&); A

5 program wishing to use a mathematical function such as cos would need to include a mathematics li,rar# header file.
-include .stdio.h/ -include .math.h/ main () 0 dou%le x(y;

y = sin (x); printf (&Jaths li%rary ready&); A

5 particular operating s#stem might re8uire its own special li,rar# for certain operations such as using a mouse or for opening windows in a GU. environment, for example. These details will ,e found in the local manual for a particular C compiler or operating s#stem. 5lthough there is no limit, in principle, to the num,er of li,raries which can ,e included in a program, there ma# ,e a practical limit- namel# memor#, since ever# li,rar# adds to the siAe of ,oth source and o,?ect code. Li,raries also add to the time it ta*es to compile a program. 4ome operating s#stems are smarter than others when running programs and can load in onl# what the# need of the large li,raries. 1thers have to load in ever#thing ,efore the# can run a program at all, so man# li,raries would slow them down. To *now what names li,raries have in a particular operating s#stem #ou have to search through its documentation. Unix users are luc*# in having an online manual which is ,etter than most written ones.

>uestions -

(uestions
%. 7ow is a li,rar# file incorporated into a C programF ". Name the most common li,rar# file in C. G. .s it possi,le to define new functions with the same names as standard li,rar# functionsF . <hat is another name for a li,rar# fileF

Progra##ing st,le
The shape of progra$s to co$e. C is actuall# a free format language. This means that there are no rules a,out how it must ,e t#ped, when to start new lines, where to place ,rac*ets or whatever. This has ,oth advantages and dangers. The advantage is that the user is free to choose a st#le which ,est suits him or her and there is freedom in the wa# in which a program can ,e structured. The disadvantage is that, unless a strict st#le is adopted, ver# slopp# programs can ,e the result. The reasons for choosing a well structured st#le are that

Long programs are $anageable onl# if programs are properl# organiAed. Programs are onl# understandable if care is ta*en in choosing the names of varia,les and functions. .t is much easier to find parts of a program if a strict ordering convention is maintained. 4uch a scheme ,ecomes increasingl# difficult to achieve with the siAe and complexit# of the pro,lem.

No simple set of rules can ever provide the ultimate solution to writing good programs. .n the end, experience and good ?udgement are the factors which decide whether a program is written well or poorl# written. The main goal of an# st#le is to achieve clarity. Previousl# restrictions of memor# siAe, power and of particular compilers often forced restrictions upon st#le, ma*ing programs clustered and difficult. 5ll computers toda# are e8uipped with more than enough memor# for their purposes, and have ver# good optimiAers which can produce faster code than most programmers could write themselves without help, so there are few good reasons not to ma*e programs as clear as possi,le.

"he for# of a ! $rogra#


)hat goes into a * progra$+ )hat will it look like+ C is made up entirel# of ,uilding ,loc*s which have a particular Ishape9 or form. The form is the same ever#where in a program, whether it is the form of the main program or of a su,routine. 5 program is made up of functions, functions are made up of statements and declarations surrounded ,# curl# ,races 0 A. The ,asic ,uilding ,loc* in a C program is the function. Ever# C program is a collection of one or more functions, written in some ar,itrar# order. 1ne and onl# one of these functions in the program must have the name main(). This function is alwa#s the starting point of a C program, so the simplest C program would ,e ?ust a single function definitionmain () 0 A

The parentheses () which follow the name of the function must ,e included even though the# apparentl# serve no purpose at this stage. This is how C distinguishes functions from

ordinar# varia,les. The function main() does not have to ,e at the top of a program so a C program does not necessaril# start at line %. .t alwa#s starts where mainBC is. 5lso, the function main()

cannot ,e called from an# other function in the program. 1nl# the operating s#stem can call the function main()- this is how a C program is started. The next most simple C program is perhaps a program which calls a function doKnothing and then ends.
)******************************************************) )* *) )* ,rogram : do nothing *) )* *) )******************************************************) main() 0 doKnothing(); A )******************************************************) doKnothing() 0 A )* Lunction called *) )* Jain program *)

The program now consists of two functions, one of which is called ,# the other. There are several new things to notice a,out this program. 2irstl# the function doKnothing() is called ,# t#ping its name followed ,# the characteristic () ,rac*ets and a semi;colon. This is all that is re8uired to transfer control to the new function. .n some languages, words li*e C5LL or P/1C are used, or even a s#m,ol li*e M. No such thing is needed in C. The semi;colon is vital however. 5ll instructions in C must end with a semi;colon. This is a signal to inform the compiler that the end of a statement has ,een reached and that an#thing which follows is meant to ,e a part of another statement. This helps the compiler diagnose errors. The I,race9 characters 0 and A mar* out a block into which instructions are written. <hen the program meets the closing ,race A it then transfers ,ac* to main() where it meets another A ,race and the program ends. This is the simplest wa# in which control flows ,etween functions in C. 5ll functions have the same status as far as a program is concerned. The function main() is treated ?ust as an# other function. <hen a program is compiled, each function is compiled as a separate entit# and then at the end the lin*er phase in the compiler attempts to sew them all together. The examples a,ove are o,viousl# ver# simple ,ut the# illustrate how control flows in a C program. 7ere are some more ,asic elements which we shall cover.

comments preprocessor commands functions declarations

varia,les statements

The s*eleton plan of a program, shown ,elow, helps to show how the elements of a C program relate. The following chapters will then expand upon this as a *ind of ,asic plan.
)****************************************************) )* *) )* +6eleton program plan *) )* *) )****************************************************) -include .stdio.h/ -include .myfile.c/ -define +DRB1J -define NUJ9BRKGLK9GNB+ )* ,reprocessor defns *) &arghhhhh& #$5

)****************************************************) main () 0 int a(%; a=random(); %=function#(); function$(a(%); A )****************************************************) function# () 0 .... A )****************************************************) function$ (a(%) int a(%; 0 .... A )* ,urpose *) )* ,urpose *) )* Jain program M start *) )* declaration *)

>uestion H-

Neither comments nor preprocessor commands have a special place in this list- the# do not have to ,e in an# one particular place within the program.

(uestions

%. ". G. .

<hat is a ,loc*F Name the six ,asic things which ma*e up a C program. 6oes a C program start at the ,eginningF B<here is the ,eginningFC <hat happens when a program comes to a J characterF <hat does this character signif#F H. <hat vital piece of punctuation goes at the end of ever# simple C statementF

!o##ents
"nnotating progra$s. Comments are a wa# of inserting remar*s and reminders into a program without affecting its content. Comments do not have a fixed place in a program- the compiler treats them as though the# were white space or ,lan* characters and the# are conse8uentl# ignored. Programs can contain an# num,er of comments without losing speed. This is ,ecause comments are stripped out of a source program ,# the compiler when it converts the source program into machine code. Comments are mar*ed out or deli$ited ,# the following pairs of characters)* ...... comment ......*)

+ecause a comment is s*ipped over as though it were a single space, it can ,e placed an#where where spaces are valid characters, even in the middle of a statement, though this is not to ,e encouraged. =ou should tr# to minimiAe the use of comments in a program while tr#ing to maximiAe the reada,ilit# of the program. .f there are too man# comments #ou o,scure #our code and it is the code which is the main message in a program.

Example commentExample comment ">uestion (-

%*a#$le 1
main () 0 )* 3his little line )* 3his little line )* 3his little line to the next line )* 1nd so on ... *) A has no effect *) has none *) went all the way down *) )* 3he almost tri4ial program *)

%*a#$le .
-include .stdio.h/ -define NG3L N +HB< )* header file *) @

)**********************************************) )* 1 %ar li6e the one a%o4e can %e used to *) )* separate functions 4isi%ly in a program *) main () 0 int i; do 0 )* Nothing III *) A while (NG3L N +HB<); A )* declarations *)

(uestion
%. <hat happens if a comment is not endedF That is if the programmer t#pes )* .. to start ,ut forgets the ..*) to closeF

-unctions
.aking black bo%es. Sol!ing proble$s. /etting results. 5 function is a module or ,loc* of program code which deals with a particular tas*. )a*ing functions is a wa# of isolating one ,loc* of code from other independent ,loc*s of code. 2unctions serve two purposes. The# allow a programmer to sa#- Ithis piece of code does a specific ?o, which stands ,# itself and should not ,e mixed up with an#ting else9, and the# ma*e a ,loc* of code reusable since a function can ,e reused in man# different contexts without repeating parts of the program text. 2unctions help us to organiAe a program in a simple wa#@ in Kernighan 0 /itchie C the# are alwa#s written in the following formidentifier (parameter1(parameter2(..) types of parameters

0 variable declarations statements.. ...... .... A

2or example
,ythagoras(x(y(N) dou%le x(y(N; 0 dou%le d; d = sOrt(x*xPy*yPN*N); printf(&3he distance to your point was 'f2n&(d); A

.n the newer 5N4. standard, the same function is written slightl# differentl#,ythagoras(dou%le x( dou%le y( dou%le N) 0 dou%le d; d = sOrt(x*xPy*yPN*N); printf(&3he distance to your point was 'f2n&(d); A

=ou will pro,a,l# see ,oth st#les in C programs. Each function has a name or identifier ,# which is used to refer to it in a program. 5 function can accept a num,er of para$eters or values which pass information from outside, and consists of a num,er of statements and declarations, enclosed ,# curl# ,races 0 A, which ma*e up the doing part of the o,?ect. The declarations and It#pe of parameter9 statements are formalities which will ,e descri,ed in good time. The name of a function in C can ,e an#thing from a single letter to a long word. The name of a function must ,egin with an alpha,etic letter or the underscore K character ,ut the other characters in the name can ,e chosen from the following groupsa .. N 1 .. F @ .. > K

Ban# letter from a to AC Ban# letter from 5 to LC Ban# digit from ! to &C Bthe underscore characterC

This means that sensi,le names can easil# ,e chosen for functions ma*ing a program eas# to read. 7ere is a real example function which adds together two integer num,ers a and % and prints the result c. 5ll the varia,les are chosen to ,e integers to *eep things simple and the result is printed out using the print;formatted function printf, from the the standard li,rar#, with a &'d& to indicate that it is printing a integer.
1ddK3woKNum%ers (a(%) int a(%; 0 int c; c = a P %; printf (&'d&(c); A )* 1dd a and % *)

Notice the position of the function name and where ,races and semi;colons are placedthe# are crucial. The details are 8uic*l# learned with practice and experience. This function is not much use standing alone. .t has to ,e called from somewhere. 5 function is called Bi.e. control is passed to the functionC ,# using its name with the usual ,rac*ets BC to follow it, along with the values which are to ,e passed to the functionmain () 0 int c(d; c = #; d = 85; 1ddK3woKNum%ers (c(d); 1ddK3woKNum%ers (#($); A

The result of this program would ,e to print out the num,er H and then the num,er G and then stop. 7ere is a simple program which ma*es use of some functions in a pla#ful wa#. The structure diagram shows how this can ,e visualiAed and the significance of the program Ilevels9. The idea is to illustrate the wa# in which the functions connect together

4tructure diagramProgram listing2unctions with values+rea*ing out earl#The exit function2unctions and t#pes>uestions M-

/tructure diagra#
Ee4el @: main () Q Ee4el #: ) Ee4el $: <ownGne () ) 2 2 <ownRight()

<ownEeft()

Note- not all functions fit into a tid# hierarch# li*e these. 4ome functions call themselves, while others can ,e called from an#where in a program. <here would #ou place the printf function in this hierarch#F

Progra# Listing
)***********************************************) )* *) )* Lunction +na6es M Eadders *) )* *) )***********************************************) -include .stdio.h/ )***********************************************) )* Ee4el @ *) )***********************************************) main () 0 printf (&3his is le4el @: the main program2n&); printf (&1%out to go down a le4el 2n&); <ownGne (); printf (&9ac6 at the end of the startII2n&); A )************************************************) )* Ee4el # *) )************************************************) <ownGne () )* 9ranch outI *)

0 printf (&<own here at le4el #( all is well2n&); <ownEeft ($);

printf (&3hrough le4el #....2n&); <ownRight ($); printf (&Roing %ac6 up a le4elI2n); A )************************************************) )* Ee4el $ *) )************************************************) <ownEeft (a) int a; 0 printf (&3his is deepest le4el 'd2n&(a); printf (&Gn the left %ranch of the picture2n&); printf (&Roing upII&); A )************************************************) <ownRight (a) int a; 0 printf (&1nd le4el 'd againI2n&(a); A )* Right %ranch *) )* Eeft %ranch *)

-unctions with values


.n other languages and in mathematics a function is understood to ,e something which produces a value or a num,er. That is, the whole function is thought of as having a value. .n C it is possi,le to choose whether or not a function will have a value. .t is possi,le to ma*e a function hand ,ac* a value to the place at which it was called. Ta*e the following example%ill = Dalculate9ill(data...);

The varia,le %ill is assigned to a function Dalculate9ill() and data are some data which are passed to the function. This statement ma*es it loo* as though Dalculate9ill() is a num,er. <hen this statement is executed in a program, control will ,e passed to the function Dalculate9ill() and, when it is done, this function will then hand control ,ac*. The value of the function is assigned to D,illD and the program continues. 2unctions which wor* in this wa# are said to return a value. .n C, returning a value is a simple matter. Consider the function Calculate+illBC from the statement a,oveDalculate9ill(starter(main(dessert) )* 1dds up 4alues *)

int starter(main(dessert; 0 int total; total = starter P main P dessert; return (total); A

5s soon as the return statement is met Dalculate9ill() stops executing and assigns the value total to the function. .f there were no return statement the program could not *now which value it should associate with the name Dalculate9ill and so it would not ,e meaningful to spea* of the function as having one value. 2orgetting a return statement can ruin a program. 2or instance if Dalculate9ill had ?ust ,eenDalculate9ill (starter(main(dessert) int starter(main(dessert; 0 int total; total = starter P main P dessert; A )* ?RGNRI *)

then the value %ill would ?ust ,e gar,age Bno predicta,le valueC, presuming that the compiler allowed this to ,e written at all. 1n the other hand if the first version were used Bthe one which did use the return(total) statementC and furthermore no assignment were mademain () 0 Dalculate9ill (#($(5); A

then the value of the function would ?ust ,e discarded, 8uite legitimatel#. This is usuall# what is done with the input output functions printf() and scanf() which actuall# return values. 4o a function in C can return a value ,ut it does not have to ,e used@ on the other hand, a value which has not ,een returned cannot ,e used safel#. 01T( 2 3unctions do not ha!e to return integers2 you can decide whether they should return a different data type or e!en no !alue at all. 4See ne%t chapter5

Breaking out earl,


4uppose that a program is in the middle of some aw*ward process in a function which is not main(), perhaps two or three loops wor*ing together, for example, and suddenl# the function finds its answer. This is where the ,eaut# of the return statement ,ecomes clear. The program can simpl# call return(4alue) an#where in the function and control

will ?ump out of an# num,er of loops or whatever and pass the value ,ac* to the calling statement without having to finish the function up to the closing ,race A.
myfunction (a(%) int a(%; 0 while (a . %) 0 if (a / %) 0 return (%); A a = a P #; A A )* %rea6ing out of functions early *)

The example shows this. The function is entered with some values for a and % and, assuming that a is less than %, it starts to execute one of C9s loops called while. .n that loop, is a single if statement and a statement which increases a ,# one on each loop. .f a ,ecomes ,igger than % at an# point the return(%) statement gets executed and the function myfunction 8uits, without having to arrive at the end ,race A, and passes the value of % ,ac* to the place it was called.

"he exit() function


The function called exit() can ,e used to terminate a program at an# point, no matter how man# levels of function calls have ,een made. This is called with a return code, li*e this-define DG<B exit (DG<B); @

This function also calls a num,er of other functions which perform tid#;up duties such as closing open files etc.

-unctions and ",$es


5ll the varia,les and values used up to now have ,een integers. +ut what happens if a function is re8uired to return a different *ind of value such as a characterF 5 statement li*e%ill = Dalculate9ill (a(%(c);

can onl# ma*e sense if the varia,le %ill and the value of the function Dalculate9ill() are the same *ind of o,?ect- in other words if Dalculat9ill() returns a floating point num,er, then %ill cannot ,e a character: +oth sides of an assignment must match.

.n fact this is done ,# declaring functions to return a particular t#pe of data. 4o far no declarations have ,een needed ,ecause C assumes that all values are integers unless #ou specificall# choose something different. 6eclarations are covered in the next section.

(uestions
%. ". G. . <rite a function which ta*es two values a and b and returns the value of BaNbC. .s there an#thing wrong with a function which returns no valueF <hat happens if a function returns a value ,ut it is not assigned to an#thingF <hat happens if a function is assigned to an o,?ect ,ut that function returns no valueF H. 7ow can a function ,e made to 8uit earl#F

0aria les, ",$es and 'eclarations


Storing data. Descri$inating types. Declaring data. 5 varia,le is a se8euence of program code with a name Balso called its identifierC. 5 name or identifier in C can ,e an#thing from a single letter to a word. The name of a varia,le must ,egin with an alpha,etic letter or the underscore K character ,ut the other characters in the name can ,e chosen from the following groupsa .. N 1 .. F @ .. > K

Ban# letter from a to AC Ban# letter from 5 to LC Ban# digit from ! to &C Bthe underscore characterC

4ome examples of valid varia,le names area total GutKofKJemory S1R integer etc...

.n C varia,les do not onl# have names- the# also have t#pes. The type of a varia,le conve#s to the the compiler what sort of data will ,e stored in it. .n +54.C and in some older, largel# o,solete languages, li*e PLE%, a special naming convention is used to determine the sort of data which can ,e held in particular varia,les. e.g. the dollar s#m,ol T is commonl# used in +54.C to mean that a varia,le is a string and the percentage ' s#m,ol is used to indicate an integer. No such convention exists in C. .nstead we specif# the t#pes of varia,les in their declarations. This serves two purposes

.t gives a compiler precise information a,out the amount of memor# that will have to ,e given over to a varia,le when a program is finall# run and what sort of arithmetic will have to ,e used on it Be.g. integer onl# or floating point or noneC.

.t provides the compiler with a list of the varia,les in a convenient place so that it can cross chec* names and t#pes for an# errors.

There is a lot of different possi,le t#pes in C. .n fact it is possi,le for us to define our own, ,ut there is no need to do this right awa#- there are some ,asic t#pes which are provided ,# C read# for use. The names of these t#pes are all reserved words in C and the# are summariAed as followschar

5 single 54C.. character


short short int int long

5 short integer Busuall# %M;,itsC 5 short integer 5 standard integer Busuall# G";,itsC 5 long integer

long int float

5 long integer Busuall# G";,its, ,ut increasingl# M ,itsC 5 floating point or real num,er BshortC

long float dou%le 4oid enum

a long floating point num,er 5 long floating point num,er 6iscussed in a later chapter. 6iscussed in a later chapter.

4olatile

6iscussed in a later chapter. There is some repetition in these words. .n addition to the a,ove, the word unsigned can also ,e placed in front of an# of these t#pes. Unsigned means that onl# positive or Aero values can ,e used. Bi.e. there is no minus signC. The advantage of using this *ind of varia,le is that storing a minus sign ta*es up some memor#, so that if no minus sign is present, larger num,ers can ,e stored in the same *ind of varia,le. The 5N4. standard also allows the word signed to ,e placed in front of an# of these t#pes, so indicate the opposite of unsigned. 1n some s#stems varia,les are signed ,# default, whereas on others the# are not.

6eclarations<here to declare things6eclarations and .nitialiAationT#pesChoosing 3aria,les5ssigning varia,les to one anotherT#pes and The Cast 1perator4torage class register static and extern-

2unctions t#pes>uestionsdeclare-

'eclarations
To declare a varia,le in a C program one writes the type followed ,# a list of varia,le na$es which are to ,e treated as ,eing that t#petypename variablename1(..(..(variablenameN;

2or exampleint i(U; char ch; dou%le x(y(N(fred; unsigned long int NameKofKSaria%le;

2ailing to declare a varia,le is more ris*# than passing through customs and failing to declare #our six tonnes of 4wiss chocolate. 5 compiler is mar*edl# more efficient than a customs officer- it will catch a missing declaration ever# time and will terminate a compiling session whilst complaining ,itterl#, often with a host of messages, one for each use of the undeclared varia,le.

1here to declare things


There are two *inds of place in which declarations can ,e made, 4ee 4cope. 2or now it will do to simpl# state what these places are. %. 1ne place is outside all of the functions. That is, in the space ,etween function definitions. B5fter the -include lines, for example.C 3aria,les declared here are called glo,al varia,les. There are also called static and external varia,les in special cases.C
$. -include .stdio.h/ 5. 7. int glo%alinteger; 8. :. float glo%alKfloatingKpoint; ;. =. main () >. #@.0 ##.A #$. )* HereI outside 0A *)

%G. The other place where declarations can ,e made is following the opening ,race, OJ, of a ,loc*. 5n# ,loc* will do, as long as the declaration follows immediatel# after the opening ,race. 3aria,les of this *ind onl# wor* inside their ,races OJ and are often called local varia,les. 5nother name for them is automatic varia,les.
#7. main () #8. #:. 0 int a;

#;. float x(y(N; #=. #>. )* statements *) $@. $#. A $$.

or
function () 0 int i; )* .... *) while (i . #@) 0 char ch; int g; )* ... *) A A

'eclarations and Initiali2ation


<hen a varia,le is declared in C, the language allows a neat piece of s#ntax which means that varia,les can ,e declared and assigned a value in one go. This is no more efficient than doing it in two stages, ,ut it is sometimes tidier. The followingint i = @; char ch = "a";

are e8uivalent to the more longwinded


int i; char ch; i = @; ch = "a";

This is called initiali6ation of the varia,les. C alwa#s allows the programmer to write declarationsEinitialiAers in this wa#, ,ut it is not alwa#s desira,le to do so. .f there are ?ust one or two declarations then this initialiAation method can ma*e a program neat and tid#. .f there are man#, then it is ,etter to initialiAe separatel#, as in the second case. 5 lot means when it starts to loo* as though there are too man#. .t ma*es no odds to the compiler, nor Bideall#C to the final code whether the first or second method is used. .t is onl# for tidiness that this is allowed.

Individual ",$es
char

charExample special charsintegers2loat-

5 character t#pe is a varia,le which can store a single 54C.. character. Groups of char form strings. .n C single characters are written enclosed ,# single 8uotes, e.g. "c": BThis is in contrast to strings of man# characters which use dou,le 8uotes, e.g. &string&C 2or instance, if ch is the name of a characterchar ch; ch = "a";

would give ch the value of the character a. The same effect can also ,e achieved ,# writingchar ch = "a";

5 character can ,e an# 54C.. character, printa,le or not printa,le from values ;%"' to %"(. B+ut onl# ! to %"( are used.C Control characters i.e. non printa,le characters are put into programs ,# using a ,ac*slash 2 and a special character or num,er. The characters and their meanings are2%

,ac*space +4
2f 2n 2r 2t 24 2& 2" 22 2ddd

form feed 22 Balso clear screenC new line NL Bli*e pressing returnC carriage return C/ Bcursor to start of lineC horiAontal ta, 7T vertical ta, Bnot all versionsC dou,le 8uotes Bnot all versionsC single 8uote character 9 ,ac*slash character P character ddd where ddd is an 54C.. code given in octal or ,ase ', 4ee Character Conversion Ta,le.

2xddd

character ddd where ddd is an 54C.. code given in hexadecimal or ,ase %M, 4ee Character Conversion Ta,le.

Listing
)***************************************************) )* *) )* +pecial Dharacters *) )* *) )***************************************************) -include .stdio.h/ main () 0 printf (&9eepI 2; 2n&); printf (&ch = 2"a2" 2n&); printf (& .- +tart of this lineII 2r&); A

The output of this program is9eepI (and the BELL sound ) ch = "a" .- +tart of this lineII

and the text cursor is left where the arrow points. .t is also possi,le to have the t#peunsigned char

This admits 54C.. values from ! to "HH, rather than ;%"' to %"(.

Integers

1hole nu# ers


There are five integer t#pes in C and the# are called char, int, long, long long and short. The difference ,etween these is the siAe of the integer which either can hold and the amount of storage re8uired for them. The siAes of these o,?ects depend on the operating s#stem of the computer. Even different flavours of Unix can have var#ing siAes for these o,?ects. Usuall#, the two to remem,er are int and short. int means a Inormal9 integer and short means a Ishort9 one, not that that tells us much. 1n a t#pical G" ,it microcomputer the siAe of these integers is the following3ype short 9its #: ,ossi%le Salues -5$;:= to 5$;:;

unsigned short #: int long unsigned int long long 5$ 5$ 5$ :7

@ to :8858 -$#7;7=5:7= to $#7;7=5:7; (ditto) @ to 7$>7>:;$>8 ->e#= to P =e#=

.ncreasingl# though, M ,it operating s#stems are appearing and long integers are M ,its long. =ou should alwa#s chec* these values. 4ome mainframe operating s#stems are completel# M ,it, e.g. Unicos has no G" ,it values. 3aria,les are declared in the usual wa#int i(U; i = U = @;

or

short i=@(U=@;

-loating Point
There are also long and short floating point num,ers in C. 5ll the mathematical functions which C can use re8uire dou%le or long float arguments so it is common to use the t#pe float for storage onl# of small floating point num,ers and to use dou,le elsewhere. BThis not alwa#s true since the C Icast9 operator allows temporar# conversions to ,e made.C 1n a t#pical G" ,it implementation the different t#pes would ,e organiAed as follows3ype float dou%le long float long dou%le 9its 5$ :7 5$ VVV ,ossi%le Salues P)- #@B-5; to P)- #@B5= P)- #@B-5@; to P)- #@B5@= (ditto)

T#pical declarationsfloat x(y(N; x = @.#; y = $.78:B8 N = @; dou%le %ignum(smallnum; %ignum = $.5:B$@=; smallnum = 5.$B-5@@;

!hoosing 0aria les


The sort of procedure that #ou would adopt when choosing varia,le names is something li*e the following

6ecide what a varia,le is for and what t#pe it needs to ,e. Choose a sensi,le name for the varia,le. 6ecide where the varia,le is allowed to exist. 6eclare that name to ,e a varia,le of the chosen t#pe.

4ome local varia,les are onl# used temporaril#, for controlling loops for instance. .t is common to give these short names Bsingle charactersC. 5 good ha,it to adopt is to *eep to a consistent practice when using these varia,les. 5 common one, for instance is to use the lettersint i(U(6;

to ,e integer t#pe varia,les used for counting. BThere is not particular reason wh# this should ,e@ it is ?ust common practice.C 1ther integer values should have more meaningful names. 4imilarl# names li*edou%le x(y(N;

tend to ma*e one thin* of floating point num,ers.

3ssigning varia les to one another


3aria,les can ,e assigned to num,ers4ar = #@;

and assigned to each other4ar# = 4ar$;

.n either case the o,?ects on either side of the = s#m,ol must ,e of the same t#pe. .t is possi,le Bthough not usuall# sensi,leC to assign a floating point num,er to a character for instance. 4o
int a( % = #; a = %;

is a valid statement, and-

float x = #.7; char ch; ch = x;

is a valid statement, since the truncated value % can ,e assigned to ch. This is a 8uestiona,le practice though. .t is unclear wh# an#one would choose to do this. Numerical values and characters will interconvert ,ecause characters are stored ,# their 54C.. codes Bwhich are integers:C Thus the following will wor*int i; char ch = "1"; i = ch; printf (&3he 1+D code of 'c is 'd&(ch(i);

The result of this would ,e3he 1+D code of 1 is :8

",$es and "he !ast +$erator


.t is worth mentioning ,riefl# a ver# valua,le operator in C- it is called the cast operator and its function is to convert one t#pe of value into another. 2or instance it would convert a character into an integerint i; char ch = "2n"; i = (int) ch;

The value of the integer would ,e the 54C.. code of the character. This is the onl# integer which it would ma*e an# sense to tal* a,out in connection with the character. 4imilarl# floating point and integer t#pes can ,e interconvertedfloat x = 5.5; int i; i = (int) x;

The value of i would ,e G ,ecause an integer cannot represent decimal points, so the cast operator rounds the num,er. There is no such pro,lem the other wa# around.

float x; int i = #$; x = (float) i;

The general form of the cast operator is therefore(type) variable

.t does not alwa#s ma*e sense to convert t#pes. This will ,e seen particularl# with regard to structures and unions. Cast operators crop up in man# areas of C. This is not the last time the# will have to ,e explained.
)***************************************************) )* *) )* <emo of Dast operator *) )* *) )***************************************************) -include .stdio.h/ main () 0 float x; int i; char ch; x = $.578; i = (int) x; ch = (char) x; printf (&Lrom float x ='f i ='d ch ='c2n&(x(i(ch); )* Use int float and char *)

i = 78; x = (float) i; ch = (char) i; printf (&Lrom int i='d x='f ch='c2n&(i(x(ch); ch = "*"; i = (int) ch; x = (float) ch; printf (&Lrom char ch='c i='d x='f2n&(ch(i(x); A

/torage class static and extern


4ometimes C programs are written in more than one text file. .f this is the case then, on occasion, it will ,e necessar# to get at varia,les which were defined in another file. .f the word extern is placed in front of a varia,le then it can ,e referenced across filesile 1 ile 2 int i; main () 0 extern int i; A 0 A function ()

.n this example, the function main() in file % can use the varia,le i from the function main in file ". 5nother class is called static. The name static is given to varia,les which can hold their values ,etween calls of a function- the# are allocated once and once onl# and their values are preserved ,etween an# num,er of function calls. 4pace is allocated for static varia,les in the program code itself and it is never disposed of unless the whole program is. N1TE- Ever# glo,al varia,le, defined outside functions has the t#pe static automaticall#. The opposite of static is auto.

-unctions, ",$es and 'eclarations


2unctions do not alwa#s have to return values which are integers despite the fact that this has ,een exclusivel# the case up to now. Unless something special is done to force a function to return a different *ind of value C will alwa#s assume that the t#pe of a function is int. .f #ou want this to ,e different, then a function has to ,e declared to ,e a certain t#pe, ?ust as varia,les have to ,e. There are two places where this must ,e done-

The name of the function must ,e declared a certain t#pe where the function is declared. e.g. a function which returns a float value must ,e declared asfloat function# () 0 return (#.$$>); A

5 function which returns a characterchar function$ () 0 return ("*"); A

5s well as declaring a function9s identifier to ,e a certain t#pe in the function definition, it must Birritatingl#C ,e declared in the function in which it is called too: The reasons for this are related to the wa# in which C is compiled. 4o, if the two functions a,ove were called from main(), the# would have to declared in the varia,les section asmain () 0 char ch( function$ (); float x( function# (); x = function# (); ch = function$ (); A

.f a function whose t#pe is not integer is not declared li*e this, then compilation errors will result: Notice also that the function must ,e declared inside ever# function which calls it, not ?ust main().

(uestions
%. <hat is an identifierF ". 4a# which of the following are valid C identifiers%. Ralph$5 ". =@shillings G. missionKcontrol . 1' H. 1T M. Koff G. <rite a statement to declare two integers called i and U. . <hat is the difference ,etween the t#pes floa and dou%le. H. <hat is the difference ,etween the t#pes int and unsigned intF

M. <rite a statement which assigns the value M( to the integer varia,le D.D. (. <hat t#pe does a C function return ,# defaultF '. .f we want to declare a function to return long float, it must ,e done in, at least, two places. <here are theseF &. <rite a statement, using the cast operator, to print out the integer part of the num,er "G.%"HM. %!. .s it possi,le to have an automatic glo,al varia,leF

Para#eters and -unctions


)ays in and out of functions. Not all functions will ,e as simple as the ones which have ,een given so far. 2unctions are most useful if the# can ,e given information to wor* with and if the# can reach varia,les and data which are defined outside of them. Examples of this have alread# ,een seen in a limited wa#. 2or instance the function Dalculate9ill accepted three values a,% and c.
Dalculate9ill (a(%(c) int a(%(c; 0 int total; total = a P % P c; return total; A

<hen varia,le values are handed to a function, ,# writing them inside a functions ,rac*ets li*e this, the function is said to accept parameters. .n mathematics a parameter is a varia,le which controls the ,ehaviour of something. .n C it is a varia,le which carries some special information. .n Dalculate9ill the D,ehaviourD is the addition process. .n other words, the value of total depends upon the starting values of a,% and c. Parameters are a,out communication ,etween different functions in a program. The# are li*e messengers which pass information to and from different places. The# provide a wa# of getting information into a function, ,ut the# can also ,e used to hand information ,ac*. Parameters are usuall# split into two categories- !alue parameters and !ariable parameters. 3alue parameters are one;wa# communication carr#ing information into a function from somewhere outside. 3aria,le parameters are two;wa#.

6eclaring parameters3alue parameters2unctions as actual parametersExample "Example G3aria,le parametersExample -

'eclaring Para#eters
5 function was defined ,# code which loo*s li*e thisidentifier (parameters...) types of parameters 0 A

Parameters, li*e varia,les and functions, also have t#pes which must ,e declared. 2or instancefunction# (i(U(x(y) int i(U; float x(y; 0 A

or
char function$ (x(ch) dou%le x; char ch; 0 char ch$ = "*"; return (ch$); A

Notice that the# are declared outside the ,loc* ,races.

0alue Para#eters
5 value parameter is the most common *ind of parameter. 5ll of the examples up to *now have ,een examples of value parameters. <hen a value parameter is passes information to a function its value is copied to a new place which is completel# isolated from the place that the information came from. 5n example helps to show this. Consider a function which is called from main() whose purpose is to add together two num,ers and to print out the result.
-include .stdio.h/ main ()

0 add (#(7); A )*******************************************) add (a(%) int a(%; 0 printf (&'d&( aP%); A

<hen this program is run, two new varia,les are automaticall# created ,# the language, called a and %. The value % is copied into a and the value is copied into %. 1,viousl# if a and , were given new values in the function add() then this could not change the values % and in main(), ,ecause % is alwa#s % and is alwa#s . The# are constants.

7owever if instead the program had ,eenmain () 0 int a = #( % = 7; add (a(%); A )**************************************)

add (a(%) int a(%; 0 printf (&'d&( aP%); A

then it is less clear what will happen. .n fact exactl# the same thing happens

<hen add() is called from main() two new varia,les a and % are created ,# the language Bwhich have nothing to do with the varia,les a and % in main() and are completel# isolated from themC. The value of a in main() is copied into the value of a in add(). The value of % in main() is copied into the value of % in add().

Now, an# reference to a and % within the function add() refers onl# to the two parameters of add and not to the varia,les with the same names which appeared in main(). This means that if a and % are altered in add() the# will not affect a and % in main(). )ore advanced computing texts have names for the old and the# new a and %"ctual Para$eters These are the original values which were handed over to a function. 5nother name for this is an argument. 3or$al Para$eters These are the copies which wor* inside the function which was called. 7ere are some points a,out value parameters.

The names of formal parameters can ,e an#thing at all. The# do not have to ,e the same as the actual parameters. 4o in the example a,ove it would ,e e8uall# valid to write-include .stdio.h/ main () 0 int a = #( % = 7; add (a(%); A )*******************************************) add (i(U) int i(U; 0

printf (&'d&( iPU); A

.n this case the value of a in main() would ,e copied to the value of i in add() and the value of % in main() would ,e copied to the value of U in add().

The parameters ought to match ,# datat#pe when ta*en in an ordered se8uence. .t is possi,le to cop# a floating point num,er into a character formal parameter, causing #ourself pro,lems which are hard to diagnose. 4ome compilers will spot this if it is done accidentall# and will flag it as an error. e.g.
main () 0 function ("*"(#.@); A )********************************) function (ch(i) char ch; int i; 0 A

is pro,a,l# wrong ,ecause %.! is a floating point value, not an integer.

The parameters ought to, ,ut need not match in num,er: This surprising fact is important ,ecause programs can go wrong if a formal parameter was missed out. 5N4. C has a wa# of chec*ing this ,# function Iprotot#ping9, ,ut in Kernighan 0 /itchie C there is no wa# to chec* this. .f the num,er of actual parameters is more than the num,er of formal parameters and all of the parameters match in t#pe then the extra values are ?ust discarded. .f the num,er of actual parameters is less than the num,er of formal parameters, then the compiler will assign some un*nown value to the formal parameters. This will pro,a,l# ,e gar,age. 1ur use of varia,les as parameters should not leave #ou with the impression that we can onl# use varia,les as parameters. .n fact, we can send an# literal value, or expression with an appropriate t#pe to a function. 2or example,
sin(5.7#7#8); cos(aP%*$.@); strlen(&3he length of this string&);

-unctions as actual $ara#eters


The value returned ,# a function can ,e used directl# as a value parameter. .t does not have to ,e assigned to a varia,le first. 2or instance-

main () 0 ,rintGut (+omeSalue()); A )*********************************************) ,rintGut (a) int a; 0 printf (&'d&(a); A )**********************************************) +omeSalue () 0 return (7$); A )* Return an ar%itrary no *) )* ,rint the 4alue *)

This often gives a concise wa# of passing a value to a function.

%*a#$le Listing
)**************************************************) )* *) )* Salue ,arameters *) )* *) )**************************************************) )* 3oying with 4alue parameters *) -include .stdio.h/ )**************************************************) )* Ee4el @ *) )**************************************************) main () )* Bxample of 4alue parameters *)

0 int i(U; dou%le x(xKplusKone(); char ch; i = @; x = @; printf (& 'f&( xKplusKone(x)); printf (& 'f&( x); U = resultof (i);

printf (& 'd&(U); A )***************************************************) )* le4el # *) )***************************************************) dou%le xKplusKone(x) dou%le x; 0 x = x P #; return (x); A )****************************************************) resultof (U) int U; 0 return ($*U P 5); A )* why not... *) )* ?or6 out some result *) )* 1dd one to x I *)

%*a#$le Listing
)******************************************************) )* *) )* ,rogram : Jore Salue ,arameters *) )* *) )******************************************************) )* ,rint out moc6 exam results etc *) -include .stdio.h/ )******************************************************) main () )* ,rint out exam results *)

0 int pupil#(pupil$(pupil5; int ppr#(ppr$(ppr5; float pen#(pen$(pen5; pupil# = =;; pupil$ = 78; pupil5 = #$; ppr# = $@@; ppr$ = $5@; ppr5 = #@; pen# = #; pen$ = $; pen5 = $@;

analyse (pupil#(pupil$(pupil5(ppr#(ppr$( ppr5(pen#(pen$(pen5); A )*******************************************************) analyse (p#(p$(p5(w#(w$(w5(%#(%$(%5) int p#(p$(p5(w#(w$(w5; float %#(%$(%5; 0 printf (&,upil # scored 'd percent2n&(p#); printf (&,upil $ scored 'd percent2n&(p$); printf (&,upil 5 scored 'd percent2n&(p5); printf (&Howe4er: 2n&); printf (&,upil# wrote 'd sides of paper2n&(w#); printf (&,upil$ wrote 'd sides2n&(w$); printf (&,upil5 wrote 'd sides2n&(w5); if (w$ / w#) 0 printf (&?hich Uust shows that Ouantity&); printf (& does not imply Ouality2n&); A printf (&,upil# used 'f %iros2n&(%#); printf (&,upil$ used 'f 2n&(%$); printf (&,upil5 used 'f 2n&(%5); printf (&3otal paper used = 'd&( total(w#(w$(w5)); A )*****************************************************) total (a(%(c) int a(%(c; 0 return (a P % P c); A )* add up total *)

0aria le Para#eters
4"s a first ti$e reader you $ay wish to o$it this section until you ha!e read about Pointers and 1perators.5 1ne wa# to hand information ,ac* is to use the return statement. This function is slightl# limited however in that it can onl# hand the value of one varia,le ,ac* at a time. There is another wa# of handing ,ac* values which is less restrictive, ,ut more aw*ward

than this. This is ,# using a special *ind of parameter, often called a varia,le parameter. .t is most easil# explained with the aid of an example-

-include .stdio.h/ main () 0 int i(U; RetSalues (Mi(MU); printf (&i = 'd and U = 'd&(i(U) A )************************************) RetSalues (p(O) int *p(*O; 0 *p = #@; *O = $@; A

To understand full# what is going on in this program re8uires a *nowledge of pointers and operators, which are covered in later sections, ,ut a ,rief explanation can ,e given here, so that the method can ,e used. There are two new things to notice a,out this program- the s#m,ols M and *. The ampersand M s#m,ol should ,e read as Dthe address of..D. The star * s#m,ol should ,e read as Dthe contents of the address...D. This is easil# confused with the multiplication

s#m,ol Bwhich is identicalC. The difference is onl# in the context in which the s#m,ol is used. 2ortunatel# this is not am,iguous since multiplication alwa#s ta*es place ,etween two num,ers or varia,les, whereas the Dcontents of a pointerD applies onl# to a single varia,le and the star precedes the varia,le name. 4o, in the program a,ove, it is not the varia,les themselves which are ,eing passed to the procedure ,ut the addresses of the the varia,les. .n other words, information a,out where the varia,les are stored in the memor# is passed to the function RetSalues(). These addresses are copied into two new varia,les p and O, which are said to ,e pointers to i and U. 4o, with varia,le parameters, the function does not receive a cop# of the varia,les themselves, ,ut information a,out how to get at the original varia,le which was passed. This information can ,e used to alter the Dactual parametersD directl# and this is done with the * operator.
*p = #@;

means- )a*e the contents of the address held in p e8ual to %!. /ecall that the address held in p is the address of the varia,le i, so this actuall# reads- ma*e i e8ual to %!. 4imilarl#*O = $@;

means ma*e the contents of the address held in O e8ual to "!. 1ther operations are also possi,le Band these are detailed in the section on pointersC such as finding out the value of i and putting it into a new varia,le, sa#, aint a; a = *p; )* is eOui4alent to a = i *)

Notice that the N s#m,ol is re8uired in the declaration of these parameters.

%*a#$le Listing
)**************************************************) )* *) )* ,rogram : Saria%le ,arameters *) )* *) )**************************************************) )* +cale some measurements on a drawing( say *) -include .stdio.h/ )**************************************************) main () 0 int height(width; )* +cale measurements*)

height = 7; width = 8; +cale<imensions (Mheight(Mwidth); printf (&+caled height = 'd2n&(height); printf (&+caled width = 'd2n&(width); A )****************************************************) +cale<imensions (h(w) int *h( *w; 0 int hscale = 5; int wscale = #; *h = *h * hscale; *w = *w * wscale; A )* scale factors *) )* return scaled 4alues *)

(uestions
%. ". G. . H. Name two wa#s that values and results can ,e handed ,ac* from a function. <here are parameters declaredF Can a function ,e used directl# as a value parameterF 6oes it mean an#thing to use a function directl# as a varia,le parameterF <hat do the s#m,ols N and 0 mean, when the# are placed in front of an identifierF M. 6o actual and formal parameters need to have the same namesF

/co$e 4 Local 3nd 5lo al


)here a progra$7s fingers can7t reach. 2rom the computer9s point of view, a C program is nothing more than a collection of functions and declarations. 2unctions can ,e thought of as sealed capsules of program code which float on a ,ac*ground of white space, and are connected together ,# means of function calls. <hite space is the name given to the white of an imaginar# piece of paper upon which a program is written, in other words the spaces and new line characters which are invisi,le to the e#e. The glo,al white space is onl# the gaps ,etween functions, not the gaps inside functions. Thin*ing of functions as sealed capsules is a useful wa# of understanding the difference ,etween local and glo,al o,?ects and the whole idea of scope in a program. 5nother analog# is to thin* of what goes on in a function as ,eing li*e watching a realit# on television. =ou cannot go in and change the T3 realit#, onl# o,serve the output, ,ut the television show draws its information from the world around it. =ou can send a

parameter Be.g. switch channelsC to ma*e some choices. 5 function called ,# a function, is li*e seeing someone watching a televsion, in a television show.

Glo,al varia,lesLocal varia,lesParameters againExample H4t#le note4cope and st#le>uestions %%-

5lo al 0aria les


Glo,al varia,les are declared in the white space ,etween functions. .f ever# function is a ship floating in this sea of white space, then glo,al varia,les Bdata storage areas which also float in this seaC can enter an# ship and also enter an#thing inside an# ship B4ee the diagramC. Glo,al varia,les are availa,le ever#where@. the# are created when a program is started and are not destro#ed until a program is stopped. The# can ,e used an#where in a program- there is no restriction a,out where the# can ,e used, in principle.

Local 0aria les


Local varia,les are more interesting. The# can not enter ?ust an# region of the program ,ecause the# are trapped inside ,loc*s. To use the ship analog#- if it is imagined that on ,oard ever# ship Bwhich means inside ever# functionC there is a large swimming pool with man# to# ships floating inside, then local varia,les will wor* an#where in the swimming pool Binside an# of the to#s ships, ,ut can not get out of the large ship into the wide ,e#ond. The swimming pool is ?ust li*e a smaller sea, ,ut one which is restricted to ,eing inside a particular function. Ever# function has its own swimming pool: The idea can ,e ta*en further too. <hat a,out swimming pools on,oard the to# shipsF B)eaning functions or ,loc*s inside the functions:
)* Rlo%al white space &sea& *) function () 0 )* Gn %oard ship *) 0 )* Gn %oard a toy ship *) A

The same rules appl# for the to# ships. 3aria,les can reach an#where inside them ,ut the# cannot get out. The# cannot escape their ,loc* ,races OJ. <henever a pair of ,loc*

,races is written into a program it is possi,le to ma*e varia,le declarations inside the opening ,race. Li*e this0 int locali; char localch; )* statements *) A

These varia,les do not exist outside the ,races. The# are onl# created when the opening ,race is encountered and the# are destro#ed when the closing ,race is executed, or when control ?umps out of the ,loc*. +ecause the# onl# wor* in this local area of a program, the# are called local varia,les. .t is a matter of st#le and efficienc# to use local varia,les when it does not matter whether varia,les are preserved outside of a particular ,loc*, ,ecause the s#stem automaticall# allocates and disposes of them. The programmer does not have to thin* a,out this. <here a varia,le is and is not defined is called the scope of that varia,le. .t tells a programmer what a varia,les horiAons are:

!o##unication 4 $ara#eters
.f functions were sealed capsules and no local varia,les could ever communicate with other parts of the program, then functions would not ,e ver# useful. This is wh# parameters are allowed. Parameters are a wa# of handing local varia,les to other functions without letting them out: 3alue parameters Bsee last sectionC ma*e copies of local varia,les without actuall# using them. The copied parameter is then a local varia,le in another function. .n other words, it can9t get out of the function to which is it passed ... unless it is passed on as another parameter.

%*a#$le Listing
Notice a,out the example that if there are two varia,les of the same name, which are ,oth allowed to ,e in the same place Bc in the example ,elowC then the more local one wins. That is, the last varia,le to ,e defined ta*es priorit#. BTechnicall# adept readers will realiAe that this is ,ecause it was the last one onto the varia,le stac*.C
)***************************************************************) )* *) )* +DG,B : 3HB DEEEB< D1,+UEB+ *) )* *) )***************************************************************) -include .stdio.h/ )***************************************************************) main ()

0 int a = #( % = $( c = 5; if (a == #) 0 int c; c = a P %; printf (&'d&(c); A handdown (a(%); printf (&'d&(c); A )**************************************************************) handdown (a(%) int a(%; 0 ... A )* +ome function *)

/t,le 6ote
4ome programmers complain a,out the use of glo,al varia,les in a program. 1ne complaint is that it is difficult to see what information is ,eing passed to a function unless all that information is passed as parameters. 4ometimes glo,al varia,les are ver# useful however, and this pro,lem need not ,e crippling. 5 wa# to ma*e this clear is to write glo,al varia,les in capital letters onl#, while writing the rest of the varia,les in mainl# small letters..
int REG91E N3BRBR; .... 0 int local integer; A

This allows glo,al varia,les to ,e spotted easil#. 5nother reason for restricting the use of glo,al varia,les is that it is easier to de,ug a program if onl# local varia,les are used. The reason is that once a function capsule is tested and sealed it can ,e guaranteed to wor* in all cases, provided it is not affected ,# an# other functions from outside. Glo,al varia,les punch holes in the sealed function capsules ,ecause the# allow ,ugs from other functions to creep into tried and tested ones. 5n alert and careful programmer can usuall# control this without difficult#. The following guidelines ma# help the reader to decide whether to use local or glo,al data-

5lwa#s thin* of using a local varia,le first. .s it impracticalF =es, if it means passing doAens of parameters to functions, or reproducing a lot of varia,les. Glo,al varia,les will sometimes tid# up a program. Local varia,les ma*e the flow of data in a program clearer and the# reduce the amount of memor# used ,# the program when the# are not in use. The preference in this ,oo* is to use local varia,les for all wor*, except where a program centres around a single data structure. .f a data structure is the main reason for a program9s existence, it is nearl# alwa#s defined glo,all#.

/co$e and /t,le


5ll the programs in this ,oo*, which are longer than a couple of lines, are written in an unusual wa#- with a le!elled structure There are several good reasons for this. 1ne is that the sealed capsules are shown to ,e sealed, ,# using a comment ,ar ,etween each function.
)**************************************)

5nother good reason is that an# function hands parameters down ,# onl# one level at a time and that an# return() statement hands values up a single level. The glo,al varia,les are *ept to a single place at the head of each program so that the# can ,e seen to reach into ever#thing. The diagram shows how the splitting of levels implies something a,out the scope of varia,les and the handing of parameters.

(uestions
%. ". G. . <hat is a glo,al varia,leF <hat is a local varia,leF <hat is meant ,# calling a ,loc* Benclosed ,# ,races 0A C a Dsealed capsuleDF 6o parameters ma*e functions lea*#F i.e. 6o the# spoil them ,# letting the varia,les lea* out into other functionsF H. <rite a program which declares varia,les. Two integer varia,les called num%erKofKhats,counter which are GL1+5L and two float varia,les called xKcoord,yKcoord which are L1C5L inside the function main(). Then add another function called another() and pass xKcoord,yKcoord to this function. 7ow man# different storage spaces are used when this program runsF B7int- are xKcoord,yKcoord and their copies the sameFC

Pre$rocessor !o##ands
.aking progra$$ing !ersatile. C is unusual in that it has a pre&processor. This comes from its Unix origins. 5s its name might suggest, the preprocessor is a phase which occurs prior to compilation of a program. The preprocessor has two main uses- it allows external files, such as header files, to ,e included and it allows macros to ,e defined. This useful feature traditionall# allowed constant values to ,e defined in Kernighan and /itchie C, which had no constants in the language. Pre;processor commands are distinguished ,# the hash Bnum,erC s#m,ol -. 1ne example of this has alread# ,een encountered for the standard header file stdio.h.
-include .stdio.h/

is a command which tells the preprocessor to treat the file stdio.h as if it were the actuall# part of the program text, in other words to include it as part of the program to ,e compiled. )acros are words which can ,e defined to stand in place of something complicated- the# are a wa# of reducing the amount of t#ping in a program and a wa# of ma*ing long ungainl# pieces of code into short words. 2or example, the simplest use of macros is to give constant values meaningful names- e.g.
-define 3BEB,HNUJ ;$@::5

This allows us to use the word 3BEB,HNUJ in the program to mean the num,er ("!MMG. .n this particular case, the word is clearl# not an# shorter than the num,er it will replace, ,ut it is more meaningful and would ma*e a program read more naturall# than if the raw num,er were used. 2or instance, a program which deals with several different fixed num,ers li*e a telephone num,er, a postcode and a street num,er could writeprintf(&'d 'd 'd&(3BEB,HNUJ(postcode(streetnum);

instead of
printf(&'d 'd 'd&(;$@::5(578(#7);

Using the macros instead ma*es the actions much clearer and allows the programmer to forget a,out what the num,ers actuall# are. .t also means that a program is eas# to alter ,ecause to change a telephone num,er, or whatever, it is onl# necessar# to change the definition, not to ret#pe the num,er in ever# single instance.

The important feature of macros is that the# are not merel# numerical constants which are referenced at compile time, ,ut are strings which are ph#sicall# replaced ,efore compilation ,# the preprocessor: This means that almost an#thing can ,e defined-define +UJ # P $ P 5 P 7

would allow +UJ to ,e used instead of #P$P5P7. 1r


-define +3R NR &Jary had a little lam%...&

would allow a commonl# used string to ,e called ,# the identifier DstringD instead of t#ping it out afresh each time. The idea of a define statement then is-define macroname definition on rest of line

)acros cannot define more than a single line to ,e su,stituted into a program ,ut the# can ,e used an#where, except inside strings. B5n#thing enclosed in string 8uotes is assumed to ,e complete and untoucha,le ,# the compiler.C 4ome macros are defined alread# in the file stdio.h such asBGL NUEE

The end of file character BQ ;% for instanceC The null character BAeroC Q !

)acro functions)acros with parametersExample MNote a,out include1ther Preprocessor commandsExample (>uestions %"-

Macro -unctions
5 more advanced use of macros is also permitted ,# the preprocessor. This involves macros which accept parameters and hand ,ac* values. This wor*s ,# defining a macro with some dumm# parameter, sa# x. 2or example- a macro which is usuall# defined in one of the standard li,raries is a%s() which means the a,solute or unsigned value of a num,er. .t is defined ,elow-define 19+(x) ((x) . @) V -(x) : (x)

The result of this is to give the positive Bor unsignedC part of an# num,er or varia,le. This would ,e no pro,lem for a function which could accept parameters, and it is, in fact, no pro,lem for macros. )acros can also ,e made to ta*e parameters. Consider the 19+() example. .f a programmer were to write 19+(7) then the preprocessor would su,stitute for x. .f a program read 19+(i) then the preprocessor would su,stitute i for x and so on.

BThere is no reason wh# macros can9t ta*e more than one parameter too. The programmer ?ust includes two dumm# parameters with different names. 4ee the example listing ,elow.C Notice that this definition uses a curious operator which ,elongs to C.test/ V .true result/ : .false result/

This is li*e a compact wa# of writing an if..then..else statement, ideal for macros. +ut it is also slightl# different- it is an expression which returns a value, where as an if..then..else is a statement with no value. 2irstl# the test is made. .f the test is true then the first statement is carried out, otherwise the second is carried out. 5s a memor# aid, it could ,e read asif .test/ then .true result/ else .false result/

B6o not ,e confused ,# the a,ove statement which is meant to show what a programmer might thin*. .t is not a valid C statement.C C can usuall# produce much more efficient code for this construction than for a corresponding if;else statement.

1hen and when not to use #acros with $ara#eters


.t is tempting to forget a,out the distinction ,etween macros and functions, thin*ing that it can ,e ignored. To some extent this is true for a,solute ,eginners, ,ut it is not a good idea to hold on to. .t should alwa#s ,e remem,ered that macros are su,stituted whole at ever# place where the# are used in a program- this is potentiall# a ver# large amount of repetition of code. The advantage of a macro, however, is speed. No time is ta*en up in passing control over to a new function, ,ecause control never leaves the home function when a macro is used- it ?ust ma*es the function a ,it longer. There is a limitation with macros though. 2unction calls cannot ,e used as their parameters, such as19+(function())

has no meaning. 1nl# varia,les or num,er constants will ,e su,stituted. )acros are also severel# restricted in complexit# ,# the limitations of the preprocessor. .t is simpl# not via,le to cop# complicated se8uences of code all over programs. Choosing ,etween functions and macros is a matter of personal ?udgement. No simple rules can ,e given. .n the end Bas with all programming choicesC it is experience which counts towards the final ends. 2unctions are easier to de,ug than macros, since the# allow us to single step through the code. Errors in macros are ver# hard to find, and can ,e ver# confusing.

%*a#$le Listing
)************************************************************) )* *) )* J1DRG <BJGN+3R13 GN *)

)* *) )************************************************************) -include .stdio.h/ -define -define -define -define -define -define -define +3R NR# +3R NR$ BC,RB++ GN BC,R$ 19+(x) J1C(a(%) 9 RRB+3(a(%(c) &1 macro definition2n& &must %e all on one lineII2n& # P $ P 5 P 7 BC,RB++ GN P #@ ((x) . @) V -(x) : (x) (a . %) V (%) : (a) (J1C(a(%) . c) V (c) : (J1C(a(%))

)************************************************************) main () 0 printf printf printf printf printf printf A )* No -definitions inside functionsI *) (+3R NR#); (+3R NR$); (&'d2n&(BC,RB++ GN); (&'d2n&(BC,R$); (&'d2n&(19+(-8)); (&9iggest of # $ and 5 is 'd&(9 RRB+3(#($(5));

6ote a out #include


<hen an include statement is written into a program, it is a sign that a compiler should merge another file of C programming with the current one. 7owever, the -include statement is itself valid C, so this means that a file which is included ma# contain -includes itself. The includes are then said to ,e DnestedD. This often ma*es includes simpler.

+ther Pre$rocessor co##ands


This section lies so$ewhat outside the $ain de!elop$ent of the book. 'ou $ight wish to o$it it on a first reading. There are a handful more preprocessor commands which can largel# ,e ignored ,# the ,eginner. The# are commonl# used in DincludeD files to ma*e sure that things are not defined twice. N1TE - true has an# non Aero value in C. false is Aero.
-undef -if

This undefines a macro, leaving the name free. This is followed ,# some expression on the same line. .t allows conditional co$pilation. .t is an advanced feature which can ,e used to sa#- onl# compile the

code ,etween -if and -endif if the value following -if is true, else leave out that code altogether. This is different from not executing code;;the code will not even ,e compiled.
-ifdef -ifndef -else -endif -line -line constant filename

This is followed ,# a macro name. .f that macro is defined then this is true. This is followed ,# a macro name. .f that name is not defined then this is true. This is part of an -if, -ifdef, -ifndef preprocessor statement. This mar*s the end of a preprocessor statement. 7as the form-

This is for de,ugging mainl#. This statement causes the compiler to ,elieve that the next line is line num,er BconstantC and is part of the file BfilenameC.
-error

This is a part of the proposed 5N4. standard. .t is intended for de,ugging. .t forces the compiler to a,ort compilation.

%*a#$le
)***********************************************************) )* 3o compile or not to compile *) )***********************************************************) -define +GJB<BL N 3 GN :87: -define DHG DB # )* Dhoose this %efore compiling *) )***********************************************************) -if (DHG DB == #) -define G,3 GN+3R NR &3he programmer selected this& -define < 33G &instead of .... & -else -define G,3 GN+3R NR &3he alternati4e& -define < 33G &i.e. 3hisI & -endif )***********************************************************) -ifdef +GJB<BL N 3 GN -define ?H13BSBR &+omething was definedI& -else -define ?H13BSBR &Nothing was defined& -endif

)************************************************************) main () 0 printf (G,3 GN+3R NR); printf (< 33G); A

(uestions
%. 6efine a macro called D,irthda#D which descri,es the da# of the month upon which #our ,irthda# falls. ". <rite an instruction to the preprocessor to include to maths li,rar# math.h. G. 5 macro is alwa#s a num,er. True or falseF . 5 macro is alwa#s a constant. True or falseF

Pointers
.aking $aps of data. =ou have a map Ba planC of the computer9s memor#. =ou need to find that essential piece of information which is stored at some un*nown location. 7ow will #ou find itF =ou need a pointer: 5 pointers is a special t#pe of varia,le which holds the address or location of another varia,le. Pointers point to these locations ,# *eeping a record of the spot at which the# were stored. Pointers to varia,les are found ,# recording the address at which a varia,le is stored. .t is alwa#s possi,le to find the address of a piece of storage in C using the special M operator. 2or instance- if location were a float t#pe varia,le, it would ,e eas# to find a pointer to it called locationKptr.
float location; float *locationKptr(*address; locationKptr = M(location);

or
address = M(location);

The declarations of pointers loo* a little strange at first. The star * s#m,ol which stands in front of the varia,le name is C9s wa# of declaring that varia,le to ,e a pointer. The four lines a,ove ma*e two identical pointers to a floating point varia,le called location, one of them is called locationKptr and the other is called address. The point is that a pointer

is ?ust a place to *eep a record of the address of a varia,le, so the# are reall# the same thing. 5 pointer is a ,undle of information that has two parts. 1ne part is the address of the ,eginning of the segment of memor# that holds whatever is pointed to. The other part is the t#pe of value that the pointer points to the ,eginning of. This tells the computer how much of the memor# after the ,eginning to read and how to interpret it. Thus, if the pointer is of a t#pe int, the segment of memor# returned will ,e four ,#tes long BG" ,itsC and ,e interpreted as an integer. .n the case of a function, the t#pe is the t#pe of value that the function will return, although the address is the address of the ,eginning of the function executa,le. .f, li*e some modern da# programmers, #ou ,elieve in sanctit# of high level languages, it is pro,a,l# a source of wonder wh# an#one <ould ever want to *now the address of these varia,les. 7aving gone to the trou,le to design a high level language, li*e C, in which varia,les can ,e given elegant and meaningful names- it seems li*e a step in the ,ac*ward direction to want to ,e a,le to find out the exact num,er of the memor# location at which it is stored: The whole point of varia,les, after all, is that it is not necessar# to *now exactl# where information is reall# stored. This is not 8uite fair though. .t is certainl# rare indeed when we should want to *now the actual num,er of the memor# location at which something is stored. That would reall# ma*e the idea of a high level language a ,it pointless. The idea ,ehind pointers is that a high level programmer can now find out the exact location of a varia,le without ever having to *now the actual num,er involved. /emem,er" pointer is a !ariable which holds the address of the storage location for another gi!en !ariable. C provides two operators M and * which allow pointers to ,e used in man# versatile wa#s.
&

Pointer operatorsUses for pointersPointers and .nitialiAationExample 'T#pes Casts and Pointers2unction pointersCalling functions ,# pointer>uestions %G-

and *

The M and * operators have alread# ,een used once to hand ,ac* values to varia,le parameters, 4ee 3alue parameters. The# can ,e read in a program to have the following meaningsM *

The address of...

The contents of the address held in... 5nother wa# of sa#ing the second of these is*

The contents of the location pointed to ,#... This reinforces the idea that pointers reach out an imaginar# hand and point to some location in the memor# and it is more usual to spea* of pointers in this wa#. The two operators * and M are alwa#s written in front of a varia,le, clinging on, so that the# refer, without dou,t, to that one varia,le. 2or instanceMx

The address at which the varia,le x is stored.


*ptr

The contents of the varia,le which is pointed to ,# ptr. The following example might help to clarif# the wa# in which the# are usedint some4ar; int *ptrKtoKsome4ar; some4ar = 7$; ptrKtoKsome4ar = M(some4ar); printf (&'d&(*ptrKtoKsome4ar); *ptrKtoKsome4ar = 8:; )* # *) )* $ *) )* 5 *) )* 7 *) )* 8 *) )* : *)

The *e# to these statements is as follows%. 6eclare an int t#pe varia,le called some4ar. ". 6eclare a pointer to an int t#pe called ptrKtoKsome4ar. The * which stands in front of ptrKtoKsome4ar is the wa# C declares ptrKtoKsome4ar as a pointer to an integer, rather than an integer. G. Let some4ar ta*e the value ". . This gives a value to ptrKtoKsome4ar. The value is the address of the varia,le some4ar. Notice that onl# at this stage does is ,ecome a pointer to the particular varia,le some4ar. +efore this, its fate is 8uite open. The declaration B"C merel# ma*es it a pointer which can point to an# integer varia,le which is around. H. Print out Dthe contents of the location pointed to ,# ptrKtoKsome4arD in other words somevar itself. 4o this will ,e ?ust ". M. Let the contents of the location pointed to ,# ptrKtoKsome4ar ,e HM. This is the same as the more direct statement;. =. some4ar = 8:;

&ses for Pointers


.t is possi,le to have pointers which point to an# t#pe of data whatsoever. The# are alwa#s declared with the * s#m,ol. 4ome examples are given ,elow.
int i(*ip; char ch(*chp; short s(*sp; float x(*xp; dou%le y(*yp;

Pointers are extremel# important o,?ects in C. The# are far more important in C than in, sa#, Pascal or +54.C B,BBW,,GWB are li*e pointersC. .n particular the# are vital when using data structures li*e strings or arra#s or lin*ed lists. <e shall meet these o,?ects in later chapters. 1ne example of the use of pointers is the C input function, which is called scanf(). .t is loo*ed at in detail in the next section. scanf() is for getting information from the *e#,oard. .t is a ,it li*e the reverse of printf(), except that it uses pointers to varia,les, not varia,les themselves. 2or example- to read an integerint i; scanf (&'d&(Mi);

or
int *i; scanf (&'d&(i);

The M sign or the * sign is vital. .f it is forgotten, scanf will pro,a,l# corrupt a program. This is one reason wh# this important function has ,een ignored up to now. 5ssem,l# language programmers might argue that there are occasions on which it would ,e nice to *now the actual address of a varia,le as a num,er. 1ne reason wh# one might want to *now this would ,e for de,ugging. .t is not often a useful thing to do, ,ut it is not inconceiva,le that in developing some program a programmer would want to *now the actual address. The M operator is flexi,le enough to allow this to ,e found. .t could ,e printed out as an integertype *ptr: printf (&1ddress = 'd&((int) ptr);

Pointers and Initiali2ation


4omething to ,e war# of with pointer varia,les is the wa# that the# are initialiAed. .t is incorrect, logicall#, to initialiAe pointers in a declaration. 5 compiler will pro,a,l# not prevent this however ,ecause there is nothing incorrect a,out it as far as s#ntax is concerned. Thin* a,out what happens when the following statement is written. This statement is reall# tal*ing a,out two different storage places in the memor#int *a = $;

2irst of all, what is declared is a pointer, so space for a Ipointer to int9 is allocated ,# the program and to start off with that space will contain gar,age Brandom num,ersC, ,ecause no statement li*e
a = Msomeint;

has #et ,een encountered which would give it a value. .t will then attempt to fill the contents of some varia,le, pointed to ,# a, with the value ". This is doomed to faliure. a onl# contains gar,age so the " could ,e stored an#where. There ma# not even ,e a varia,le at the place in the memor# which a points to. Nothing has ,een said a,out that #et. This *ind of initialiAation cannot possi,l# wor* and will most li*el# crash the program or corrupt some other data.

%*a#$le Listing
)**********************************************) )* *) )* +wapping ,ointers *) )* *) )**********************************************)

)* ,rogram swaps the 4aria%les which a(% *) )* point to. Not pointless really I *) -include .stdio.h/ main () 0 int *a(*%(*c; int 1(9; 1 = #$; 9 = >; a = M1; % = M9; )* )* )* <eclr ptrs *) )* <eclare storage *) nitialiNe storage *) nitialiNe pointers *)

printf (&'d 'd2n&(*a(*%); c = a; a = %; % = c; printf (&'d 'd2n&(*a(*%); A )* swap pointers *)

",$es, !asts and Pointers


.t is tempting ,ut incorrect to thin* that a pointer to an integer is the same *ind of o,?ect as a pointer to a floating point o,?ect or an# other t#pe for that matter. This is not necessaril# the case. Compilers distinguish ,etween pointers to different *inds of o,?ects. There are occasions however when it is actuall# necessar# to convert one *ind of pointer into another. This might happen with a t#pe of varia,le called DunionsD or even functions which allocate storage for special uses. These o,?ects are met later on in this ,oo*. <hen this situation comes a,out, the cast operator has to ,e used to ma*e sure that pointers have compati,le t#pes when the# are assigned to one another. The cast operator for varia,les, 4ee The Cast 1perator, is written in front of a varia,le to force it to ,e a particular t#pe(type) variable

2or pointers it is-

(type *) pointer

Loo* at the following statementchar *ch; int *i; i = (int *) ch;

This copies the value of the pointer ch to the pointer i. The cast operator ma*es sure that the pointers are in step and not tal*ing at cross purposes. The reason that pointers have to ,e Icast9 into shape is a ,it su,tle and depends upon particular computers. .n practice it ma# not actuall# do an#thing, ,ut it is a necessar# part of the s#ntax of C. Pointer casting is discussed in greater detail in the chapter on 4tructures and Unions.

Pointers to functions
This section is so$ewhat outside of the $ain de!elop$ent of the book. 'ou $ight want to o$it it on first reading. Let9s now consider pointers to functions as opposed to varia,les. This is an advanced feature which should ,e used with more than a little care. The idea ,ehind pointers to functions is that #ou can pass a function as a parameter to another function: This seems li*e a ,iAarre notion at first ,ut in fact it ma*es perfect sense. Pointers to functions ena,le #ou to tell an# function which su,;ordinate function it should use to do its ?o,. That means that #ou can plug in a new function in place of an old one ?ust ,# passing a different parameter value to the function. =ou do not have to rewrite an# code. .n machine code circles this is sometimes called indirection or vectoring. <hen we come to loo* at arra#s, we9ll find that a pointer to the start of an arra# can ,e found ,# using the name of the arra# itself without the s8uare ,rac*ets XY. 2or functions, the name of the function without the round ,rac*ets wor*s as a pointer to the start of the function, as long as the compiler understands that the name represents the function and not a varia,le with the same name. 4o;;to pass a function as a parameter to another function #ou would write
function#(function$);

.f #ou tr# this as it stands, a stream of compilation errors will ,e the result. The reason is that #ou must declare function$() explicitl# li*e thisint function$();

.f the function returns a different t#pe then clearl# the declaration will ,e different ,ut the form will ,e the same. The declaration can ,e placed together with other declarations. .t is not important whether the varia,le is declared locall# or glo,all#, since a function is a glo,al o,?ect regardless. <hat is important is that we declare specificall# a pointer to a function which returns a t#pe Beven if it is 4oidC. The function which accepts a function pointer as an argument loo*s li*e thisfunction# (a) int (*a)(); 0 int i;

i = (*a)(parameters); A

This declares the formal parameter a to ,e a pointer to a function returning a value of t#pe int. 4imilarl# if #ou want to declare a pointer to a function to a general t#pe typena$e with the name fnptr, #ou would do it li*e thistypename (*fnptr)();

!alling a function , $ointer


Given a pointer to a function how do we call the functionF The s#ntax is thisvariable = (*fnptr)(parameters);

5n example let us loo* at a function which ta*es an integer and returns a character.
int i; char ch( function();

Normall# this function is called using the statementch = function(i);

,ut we can also do the same thing with a pointer to the function. 2irst define
char function(); char (*fnptr)(); fnptr = function;

then call the function with


ch = (*fnptr)(i);

5 pointer to a function can ,e used to provide a *ind of plug;in interface to a logical device, i.e. a wa# of choosing the right function for the ?o,.
4oid printer()(textscreen()(windows(); switch (choice) 0 case #: fnptr = printer; %rea6; case $: fnptr = textscreen; %rea6; case 5: fnptr = windows; A

Gutput(data(fnptr);

This is the ,asis of Ipol#morphism9 found in o,?ect oriented languages- a choice of a logical BvirtualC function ,ased on some a,stract la,el Bthe choiceC. The CRR language provides an a,stract form of this with a more advanced s#ntax, ,ut this is the essence of virtual function methods in o,?ect oriented languages. B%13)%7 5 pointer to a function is an automatic local varia,le. Local varia,les are never initialiAed ,# the compiler in C. .f #ou inadvertentl# forget to initialiAe the pointer to a function, #ou will come 8uic*l# to grief. )a*e sure that #our pointers are assigned ,efore #ou use them:

(uestions
%. ". G. . <hat is a pointerF 7ow is a varia,le declared to ,e a pointerF <hat data t#pes can pointers Dpoint toDF <rite a statement which converts a pointer to a character into a pointer to a dou%le t#pe. BThis is not as pointless as it seems. .t is useful in dealing with unions and memor# allocation functions.C H. <h# is it incorrect to declare- float *num%er = $.:8; F

/tandard +ut$ut and /tandard In$ut


Talking to the user. Getting information in and out of a computer is the most important thing that a program can do. <ithout input and output computers would ,e 8uite useless. C treats all its output as though it were reading or writing to different files. 5 file is reall# ?ust an a,traction- a place where information comes from or can ,e sent to. 4ome files can onl# ,e read, some can onl# ,e written to, others can ,e ,oth read from and written

to. .n other situations files are called .E1 streams.

C has three files Balso called streamsC which are alwa#s open and read# for use. The# are called stdin, stdout and stderr, meaning standard input and standard output and standard error file. 4tdin is the input which usuall# arrives from the *e#,oard of a computer. stdout is usuall# the screen. stderr is the route ,# which all error messages pass- usuall# the screen. This is onl# Iusuall#9 ,ecause the situation can ,e altered. .n fact what happens is that these files are ?ust handed over to the local operating s#stem to deal with and it chooses what to do with them. Usuall# this means the *e#,oard and the screen, ,ut it can also ,e redirected to a printer or to a dis* file or to a modem etc.. depending upon how the user ran the program. The *e#,oard and screen are referred to as the standard inputEoutput files ,ecause this is what most people use, most of the time. 5lso the programmer never has to open or close these, ,ecause C does it automaticall#. The C li,rar# functions covered ,# stdio.h provides some methods for wor*ing with stdin and stdout. The# are simplified versions of the functions that can ,e used on an# *ind of file, 4ee 2iles and 6evices. .n order of importance, the# areprintf () scanf () getchar() putchar() gets () puts ()

printf againExample &1utput &-

printf

2ormatting with printfExample %!1utput %!4pecial Control Characters again>uestions %HscanfConversion characters7ow does scanf see the input2irst account of scanfThe dangerous functionKeeping scanf under controlExample %%)atching without assigning2ormal 6efinition of scanf4ummar# of points a,out scanf>uestions %H,Low Level .nputE1utput>uestions %Hc-

The printf function has ,een used widel# up to now for output ,ecause it provides a neat and eas# wa# of printing text and num,ers to stdout Bthe screenC. .ts name is meant to signif# formatted printing ,ecause it gives the user control over how text and numerical data are to ,e laid out on the screen. )a*ing text loo* good on screen is important in programming. C ma*es this eas# ,# allowing #ou to decide how the text will ,e printed in the availa,le space. The printf function has general formprintf (&string...&(variables(numbers)

.t contains a string Bwhich is not optionalC and it contains an# num,er of parameters to follow- one for each ,lan* field in the string. The ,lan* fields are control se8uences which one can put into the string to ,e filled in with num,ers or the contents of varia,les ,efore the final result is printed out. These fields are introduced ,# using a ' character, followed ,# some coded information, which sa#s something a,out the siAe of the ,lan* space and the t#pe of num,er or string which will ,e filled into that space. 1ften the string is called the control string ,ecause it contains these control characters. The simplest use of printf is to ?ust print out a string with no ,lan* fields to ,e filledprintf (&1 pretty ordinary string..&); printf (&3esting #($(5...&);

The next simplest case that has ,een used ,efore now is to print out a single integer num,er-

int num%er = 7$; printf (&'d&(num%er);

The two can ,e com,inedint num%er = 7$; printf (&+ome num%er = 'd&(num%er);

The result of this last example is to print out the following on the screen+ome num%er = 7$

The text cursor is left pointing to the character ?ust after the ". Notice the wa# that 'd is swapped for the num,er ". 'd defines a field which is filled in with the value of the varia,le. There are other *inds of data than integers though. 5n# *ind of varia,le can ,e printed out with printf. 'd is called a conversion character for integers ,ecause it tells the compiler to treat the varia,le to ,e filled into it as an integer. 4o it ,etter had ,e an integer or things will go wrong: 1ther characters are used for other *inds of data. 7ere is a list if the different letters for printf.
d u x o s c f e g

signed denar# integer unsigned denar# integer hexadecimal integer octal integer string single character fixed decimal floating point scientific notation floating point use f or e, whichever is shorter

The ,est wa# to learn these is to experiment with different conversion characters. The example program and its output ,elow give some impression of how the# wor*-

%*a#$le Listing
)*******************************************************) )* *) )* printf Don4ersion Dharacters and 3ypes *) )* *) )*******************************************************) -include .stdio.h/ main () 0 int i = -#@; unsigned int ui = #@; float x = 5.8:; dou%le y = 5.8$; char ch = "N"; char *stringKptr = &any old string&; printf (&signed integer 'd2n&( i); printf (&unsigned integer 'u2n&(ui); printf (&3his is wrongI 'u&(i); printf (&+ee what happens when you get the &); printf (&character wrongI&); printf (&Hexadecimal 'x 'x2n&(i(ui); printf (&Gctal 'o 'o2n&(i(ui); printf (&Lloat and dou%le 'f 'f2n&(x(y); printf (& ditto 'e 'e2n&(x(y); printf (& ditto 'g 'g2n&(x(y); printf (&single character 'c2n&(ch); printf (&whole string -/ 's&(stringKptr); A

+ut$ut
signed integer -#@ unsigned integer #@ 3his is wrongI #@+ee what happens when you get the character wrongIHexadecimal LLLLLLL: 1 Gctal 5;;;;;;;;:: #$ Lloat and dou%le 5.8:@@@@ 5.8$@@@@ ditto 5.8:@@@@BP@@ 5.8$@@@@BP@@ ditto 5.8:@@@@ 5.8$@@@@ single character N whole string -/ any old string

-or#atting with printf


The example program a,ove does not produce a ver# neat la#out on the screen. The conversion specifiers in the printf string can ,e extended to give more information. The ' and the character t#pe act li*e ,rac*ets around the extra information. e.g.
'-#@.5f

is an extended version of 'f, which carries some more information. That extra information ta*es the form' X-Y Xf!idthY X.pY C

where the each ,rac*et is used to denote that the item is optional and the s#m,ols inside them stand for the following.
Xf!idthY

This is a num,er which specifies the field width of this D,lan* fieldD. .n other words, how wide a space will ,e made in the string for the o,?ect concernedF .n fact it is the minimum field width ,ecause if data need more room than is written here the# will spill out of their ,ox of fixed siAe. .f the siAe is ,igger than the o,?ect to ,e printed, the rest of the field will ,e filled out with spaces.
X-Y

X.pY

.f this included the output will ,e left ?ustified. This means it will ,e aligned with the left hand margin of the field created with Xf!idthY. Normall# all num,ers are right ?ustified, or aligned with the right hand margin of the field D,oxD. This has different meanings depending on the o,?ect which is to ,e printed. 2or a floating point t#pe Bfloat or dou%leC p specifies the num,er of decimal places after the point which are to ,e printed. 2or a string it specifies how man# characters are to ,e printed.

4ome valid format specifiers are written ,elow here.


'#@d '$.$f '$8.$#s '$.:f

The ta,le ,elow helps to show the effect of changing these format controls. The width of a field is draw in ,# using the Q ,ars.
"b#ect to be printed 7$ 7$ 5$7 -# -# "N" $ontrol %pec& ':d '-:d '#@d '-#@d '#d '5c 'ctual "utput Q 7$Q Q7$ Q Q 5$7Q Q-# Q Q-#Q(o4erspill) Q NQ

"N" $.;#=$= $.;#=$= $.;#=$= $.;#=$= $.;#= $.;#= $.;#=$= $.;#=$= $.;#=$= &printf& &printf& &printf& &printf& &printf& &printf&

'-5c '#@f '#@.$f '-#@.$f '$.7f '.7f '#@.8f '#@e '#@.$e '#@.$g 's '#@s '$s '8.5s '-8.5s '.5s

QN

Q $.;#=$=Q Q $.;#Q Q$.;# Q Q$.;#=$Q(o4erspill) Q$.;#=@Q Q $.;#=@@Q Q$.;#=$=eP@@Q Q $.#;eP@@Q Q $.;#Q QprintfQ Q printfQ QprintfQ(o4erspill) Q priQ Qpri Q QpriQ

%*a#$le Listing
)***********************************************) )* *) )* Jultiplication 3a%le *) )* *) )***********************************************) -include .stdio.h/ main () 0 int i(U; for (i = #; i .= #@; iPP) 0 for (U = #; U .= #@; UPP) 0 printf (&'8d&(i * U); A printf (&2n&); A A )* ,rinting in columns *)

+ut$ut
# $ 5 7 8 : ; $ 7 : = #@ #$ #7 5 : > #$ #8 #= $# 7 = #$ #: $@ $7 $= 8 #@ #8 $@ $8 5@ 58 : #$ #= $7 5@ 5: 7$ ; #7 $# $= 58 7$ 7> = #: $7 5$ 7@ 7= 8: > #= $; 5: 78 87 :5 #@ $@ 5@ 7@ 8@ :@ ;@

= > #@

#: #= $@

$7 $; 5@

5$ 5: 7@

7@ 78 8@

7= 87 :@

8: :5 ;@

:7 ;$ =@

;$ =# >@

=@ >@ #@@

/$ecial !ontrol !haracters


Control characters are invisi,le on the screen. The# have special purposes usuall# to do with cursor movement. The# are written into an ordinar# string ,# t#ping a ,ac*slash character 2 followed ,# some other character. These characters are listed ,elow.
2% 2f 2n 2r 2t 24 2& 2" 22 2ddd

,ac*space +4 form feed 22 Balso clear screenC new line NL Bli*e pressing returnC carriage return C/ Bcursor to start of lineC horiAontal ta, 7T vertical ta, dou,le 8uote single 8uote character 9 ,ac*slash character 2 character ddd where ddd is an 54C.. code given in octal or ,ase ', 4ee Character Conversion Ta,le.

2xddd

character ddd where ddd is an 54C.. code given in hexadecimal or ,ase %M, 4ee Character Conversion Ta,le.

(uestions
%. <rite a program which simpl# prints out- :.$5eP@@ ". .nvestigate what happens when #ou t#pe the wrong conversion specifier in a program. e.g. tr# printing an integer with 'f or a floating point num,er with 'c. This is ,ound to go wrong ; ,ut how will it go wrongF G. <hat is wrong with the following statementsF %. printf (x); ". printf (&'d&); G. printf (); . printf (&Num%er = 'd&); 7int- if #ou don9t *now, tr# them in a program:

scanf

is the input function which gets formatted input from the file stdin Bthe *e#,oardC. This is a ver# versatile function ,ut it is also ver# eas# to go wrong with. .n fact it is pro,a,l# the most difficult to understand of all the C standard li,rar# functions.
scanf

/emem,er that C treats its *e#,oard input as a file. This ma*es 8uite a difference to the wa# that scanf wor*s. The actual mechanics of scanf are ver# similar to those of printf in reverse
scanf (&string...&(pointers);

with one important exception- namel# that it is not varia,les which are listed after the control string, ,ut pointers to varia,les. 7ere are some valid uses of scanfint i; char ch; float x; scanf (&'d 'c 'f&( Mi( Mch( Mx);

Notice the M characters which ma*e the arguments pointers. 5lso notice the conversion specifiers which tell scanf what t#pes of data it is going to read. The other possi,ilit# is that a program might alread# have pointers to a particular set of varia,les in that case the M is not needed. 2or instancefunction (i(ch(x) int *i; char *ch; float *x; 0 scanf (&'d 'c 'f&( i( ch( x); A

.n this case it would actuall# ,e wrong to write the ampersand M s#m,ol.

!onversion characters
The conversion characters for scanf are not identical to those for printf and it is much more important to ,e precise and totall# correct with these than it is with printf.
d

denar# integer Bint or long intC


ld x

long decimal integer

hexadecimal integer
o h f lf e le c s

octal integer short integer float t#pe long float or dou,le float t#pe dou,le single character character string

The difference ,etween short integer and long integer can ma*e or ,rea* a program. .f it is found that a program9s input seems to ,e ,ehaving strangel#, chec* these carefull#. B4ee the section on Errors and 6e,ugging for more a,out this.C

How does scanf see the in$ut8


<hen scanf is called in a program it chec*s to see what is in the input file, that is, it chec*s to see what the user has t#ped in at the *e#,oard. Ke#,oard input is usuall# ,uffered. This means that the characters are held in a *ind of waiting ,a# in the memor# until the# are read. The ,uffer can ,e thought of as a part of the input file stdin, holding some characters which can ,e scanned though. .f the ,uffer has some characters in it, scanf will start to loo* through these@ if not, it will wait for some characters to ,e put into the ,uffer. There is an important point here- although scanf will start scanning through characters as soon as the# are in the ,uffer, the operating s#stem often sees to it that scanf doesn9t get to *now a,out an# of the characters until the user has pressed the RB3URN or BN3BR *e# on the computer or terminal. .f the ,uffer is empt# scanf will wait for some characters to ,e put into it. To understand how scanf wor*s, it is useful to thin* of the input as coming in Ilines9. 5 line is a ,unch of characters ending in a newline character 2n. This can ,e represented ,# a ,ox li*e the one ,elow-------------------------------------Q some...chars.;5=). Q"2n"Q --------------------------------------

5s far as scanf is concerned, the input is entirel# made out of a stream of characters. .f the programmer sa#s that an integer is to ,e expected ,# using the 'd conversion specifier then scanf will tr# to ma*e sense of the characters as an integer. .n other words,

it will loo* for some characters which ma*e up a valid integer, such as a group of num,ers all ,etween ! and &. .f the user sa#s that floating point t#pe is expected then it will loo* for a num,er which ma# or ma# not have a decimal point in it. .f the user ?ust wants a character then an# character will do:

-irst account of scanf


Consider the example which was give a,ove.
int i; char ch; float x; scanf (&'d 'c 'f&( Mi( Mch( Mx);

7ere is a simplified, ideal view of what happens. scanf loo*s at the control string and finds that the first conversion specifier is 'd which means an integer. .t then tries to find some characters which fit the description of an integer in the input file. .t s*ips over an# white space characters Bspaces, newlinesC which do not constitute a valid integer until it matches one. 1nce it has matched the integer and placed its value in the varia,le i it carries on and loo*s at the next conversion specifier 'c which means a character. .t ta*es the next character and places it in ch. 2inall# it loo*s at the last conversion specifier 'f which means a floating point num,er and finds some characters which fit the description of a floating point num,er. .t passes the value onto the varia,le x and then 8uits. This ,rief account of scanf does not tell the whole stor# ,# a long wa#. .t assumes that all the characters were successfull# found and that ever#thing went smoothl#- something which seldom happens in practice:

"he dangerous function


<hat happens if scanf doesn9t find an integer or a float t#peF The answer is that it will 8uit at the first item it fails to match, leaving that character and the rest of the input line still to ,e read in the file. 5t the first character it meets which does not fit in with the conversion string9s interpretation scanf a,orts and control passes to the next C statement. This is wh# scanf is a Idangerous9 function- ,ecause it can 8uit in the middle of a tas* and leave a lot of surplus data around in the input file. These surplus data simpl# wait in the input file until the next scanf is ,rought into operation, where the# can also cause it to 8uit. .t is not safe, therefore, to use scanf ,# itself- without some chec* that it is wor*ing successfull#. is also dangerous for the opposite reason- what happens if scanf doesn9t use up all the characters in the input line ,efore it satisfies its needsF 5gain the answer is that it 8uits and leaves the extra characters in the input file stdin for the next scanf to read, exactl# where it left off. 4o if the program was meant to read data from the input and couldn9t, it leaves a mess for something else to trip over. scanf can get out of step with
scanf

its input if the user t#pes something even slightl# out of line. .t should ,e used with caution...

9ee$ing scanf under control


ma# ,e dangerous for slopp# programs which do not chec* their input carefull#, ,ut it is easil# tamed ,# using it as ?ust a part of a more sophisticated input routine and sometimes even more simpl# with the aid of a ver# short function which can ,e incorporated into an# programscanf s6ipgar%() )* s6ip gar%age corrupting scanf *)

0 while (getchar() I= "2n") 0 A A

The action of this function is simpl# to s*ip to the end of the input line so that there are no characters left in the input. .t cannot stop scanf from getting out of step ,efore the end of a line ,ecause no function can stop the user from t#ping in nonsense: 4o to get a single integer, for instance, a program could tr#int i; scanf(&'d&(Mi); s6ipgar%();

The programmer must police user;gar,age personall# ,# using a loop to the effect ofwhile (inputisnonsense) 0 printf (&Ret your act together out thereII2n&); scanf (..) s6ipgar%(); A

.t is usuall# as well to use s6ipgar%() ever# time.

%*a#$les
7ere are some example programs with example runs to show how scanf either wor*s or fails.
)****************************************) )* Bxample # *) )****************************************) -include .stdio.h/

main () 0 int i = @; char ch = "*"; float x = @; scanf (&'d 'c 'f&(Mi(Mch(Mx); printf (&'d 'c 'f2n&(i(ch(x); A

This program ?ust waits for a line from the user and prints out what it ma*es of that line. Things to notice a,out these examples are the wa# in which scanf Imisunderstands9 what the user has t#ped in and also the values which the varia,les had ,efore the scanf

function.
nput : #x$.5 Gutput: # x $.5@@@@@

The input gets ,ro*en up in the following wa#-----------------Q # Q"x"Q $.5 Q"2n"Q -----------------n this example e4erything wor6s properly. 3here are no spaces to confuse matters. it is simple for scanf to see what the first num%er is %ecause the next character is x which is not a 4alid num%er. nput : # x $.5 Gutput: # @.@@@@@@ ----------Q#Q" "Q .%rea6/ Qx $.5Q -----------

.n this example the integer is correctl# matched as %. The character is now a space and the x is left in the stream. The x does not match the description of a float value so scanf terminates, leaving x $.5 still in the input stream.
nput : . Gutput: @ * @.@@@@@@ --Q"."Q .%rea6/ ---

5 single full;stop BperiodC. scanf 8uits straight awa# ,ecause it loo*s for an integer. .t leaves the whole input line Bwhich is ?ust the period .C in the input stream.
)****************************************) )* Bxample $ *) )****************************************) -include .stdio.h/ main () 0 int i = @; char ch = "*"(ch$(ch5; float x = @; scanf (&'d 'c 'f&( Mi(Mch(Mx); scanf (&'c 'c&( Mch$(Mch5); printf (&'d 'c 'f2n 'c 'c&); A

The input for this program is: x$.5: and the output is: : @.@@@@@@ x $ --------------------Q : Q " " Q .%rea6/ Q"x"Q"$"Q .5: Q ---------------------

7ere the integer is successfull# matched with M. The character is matched with a space ,ut the float character finds an x in the wa#, so the first scanf a,orts leaving the value of x unchanged and the rest of the characters still in the file. The second scanf function then pic*s these up. .t can ,e seen that the first two characters are the x which caused the previous scanf to fail and the first " of the intended floating point num,er.
)****************************************) )* Bxample 5 *) )****************************************) -include .stdio.h/ main() 0 char ch#(ch$(ch5; scanf (&'c 'c 'c&(Mch#(Mch$(Mch5); printf (&'c 'c 'c&(ch#(ch$(ch5); A

Trialsinput : a%c output: a % c input : a XreturnY % XreturnY c XreturnY output: a % c input : $.5 output: $ . 5

Matching without assigning


allows input t#pes to ,e matched ,ut then discarded without ,eing assigned to an# varia,le. .t also allows whole se8uences of characters to ,e matched and s*ipped. 2or examplescanf scanf (&'*c&);

would s*ip a single character. The * character means do not ma*e an assignment. Note carefull# that the following is wrongscanf (&'*c&( Mch);

5 pointer should not ,e given for a dumm# conversion character. .n this simple case a,ove it pro,a,l# does not matter, ,ut in a string with several things to ,e matched, it would ma*e the conversion characters out of step with the varia,les, since scanf does not return a value from a dumm# conversion character. .t might seem as though there would ,e no sense in writingscanf (&'*s 'f 'c&(Mx(Mch);

,ecause the whole input file is one long string after all, ,ut this is not true ,ecause, as far as scanf is concerned a string is terminated ,# an# white space character, so the float t#pe x and the character ch would receive values provided there were a space or newline character after an# string. .f an# non;conversion characters are t#ped into the string scanf will match and s*ip over them in the input. 2or examplescanf (& Num%er = 'd&(Mi);

.f the input were- Num%er = $8:, scanf would s*ip over the Num%er = . 5s usual, if the string cannot ,e matched, scanf will a,ort, leaving the remaining characters in the input stream.
)****************************************) )* Bxample 7 *) )****************************************) -include .stdio.h/ main() 0 float x = @; int i = @; char ch = "*"; scanf(&+6ipthisI '*f 'd '*c&(Mi); printf(&'f 'd 'c&(x(i(ch); A nput : +6ipthisI $5 Gutput: @.@@@@@@ $5 * nput : $: Gutput: @.@@@@@@ @ *

.n this last case scanf a,orted ,efore matching an#thing.

-or#al 'efinition of scanf


The general form of the scanf function isn = scanf (&string...&( pointers);

The value n returned is the num,er of items matched or the end of file character BGL, or NUEE if the first item did not match. This value is often discarded. The control string contains a num,er of conversion specifiers with the following general form'X*YXnYC X*Y XnY

the optional assignment suppression character. this is a num,er giving the maximum field width to ,e accepted ,# scanf for a particular item. That is, the maximum num,er of characters which are to ,e thought of as ,eing part of one the current varia,le value.

is one of the characters listed a,ove. 5n# white space characters in the scanf string are ignored. 5n# other characters are matched. The pointers must ,e pointers to varia,les of the correct t#pe and the# must match the conversion specifiers in the order in which the# are written.

There are two variations on the conversion specifiers for strings, though it is ver# li*el# that man# compilers will not support this. +oth of the following impl# strings'Xset of charactersY 'XZset of charactersY

a string made up of the given characters onl#. a string which is delimited ,# the set of characters given.

2or example, to read the rest of a line of text, up to ,ut not including the end of line, into a string arra# one would writescanf(&'XZ2nY&(stringarray);

/u##ar, of $oints a out scanf

4canf wor*s across input lines as though it were dealing with a file. Usuall# the user t#pes in a line and hits return. The whole line is then thought of as ,eing part of the input file pointer stdin. .f scanf finds the end of a line earl# it will tr# to read past it until all its needs are satisfied. .f scanf fails at an# stage to match the correct t#pe of string at the correct time, it will 8uit leaving the remaining input still in the file. .f an element is not matched, no value will ,e assigned to the corresponding varia,le. <hite space characters are ignored for all conversion characters except 'c. 1nl# a 'c t#pe can contain a white space character. <hite space characters in

(uestions
%. <hat is a white space characterF ". <rite a program which fetches two integers from the user and multiplies them together. Print out the answer. Tr# to ma*e the input as safe as possi,le. G. <rite a program which ?ust echoes all the input to the output. . <rite a program which strips spaces out of the input and replaces them with a single newline character. H. scanf alwa#s ta*es pointer arguments. True or falseF

Low Level In$ut:+ut$ut


getchar and putchargets and puts-

getchar

and putchar

and printf() are relativel# high level functions- this means that the# are versatile and do a lot of hidden wor* for the user. C also provides some functions for dealing with input and output at a lower level- character ,# character. These functions are called getchar() and putchar() ,ut, in fact, the# might not ,e functions- the# could ,e macros instead, 4ee Preprocessor.
scanf() high le4el: printf() ) low le4el: putchar() Q Q Q Q Q Q Q scanf() 2 getchar()

gets a single character from the input file stdin@ putchar writes a single character to the output file stdout. getchar returns a character t#pe- the next character on the input file. 2or examplegetchar char ch; ch = getchar();

This places the next character, what ever it might ,e, into the varia,le ch. Notice that no conversion to different data t#pes can ,e performed ,# getchar() ,ecause it deals with single characters onl#. .t is a low level function and does not I*now9 an#thing a,out data t#pes other than characters. was used in the function s6ipgar%() to tame the scanf() function. This function was written in a ver# compact wa#. 5nother wa# of writing it would ,e as ,elowgetchar s6ipgar% () 0 char ch; ch = getchar(); while (ch I= "2n") 0 ch = getchar(); A A )* s6ip gar%age corrupting scanf *)

The I= s#m,ol means Dis not e8ual toD and the while statement is a loop. This function *eeps on getchar;ing until it finds the newline character and then it 8uits. This function has man# uses. 1ne of these is to cop# immediate *e#press statements of languages li*e +54.C, where a program responds to *e#s as the# are pressed without having to wait for return to ,e pressed. <ithout special li,rar# functions to give this *ind of input Bwhich are not universalC it is onl# possi,le to do this with the return *e# itself. 2or example-

printf(&,ress RB3URN to continue2n&); s6ipgar%();

does not receive an# input until the user presses RB3URN, and then it simpl# s*ips over it in one go: The effect is that it waits for RB3URN to ,e pressed.
s6ipgar%() putchar()

writes a character t#pe and also returns a character t#pe. 2or example-

char ch = "*"; putchar (ch); ch = putchar (ch);

These two alternatives have the same effect. The value returned ,# putchar() is the character which was written to the output. .n other words it ?ust hands the same value ,ac* again. This can simpl# ,e discarded, as in the first line. putchar() is not much use without loops to repeat it over and over again. 5n important point to remem,er is that putchar() and getchar() could well ,e implemented as macros, rather than functions. This means that it might not ,e possi,le to use functions as parameters inside themputchar( function() );

This depends entirel# upon the compiler, ,ut it is something to watch out for.
gets

and puts

Two functions which are similar to putchar() and getchar() are puts() and gets() which mean putstring and getstring respectivel#. Their purpose is either to read a whole string from the input file stdin or write a whole string to the output stdout. 4trings are groups or arra#s of characters. 2or instancechar *stringXlengthY; string = gets(string); puts(string);

)ore information a,out these is given later, 4ee 4trings.

(uestions
%. .s the following statement possi,leF B.t could depend upon #our compiler- tr# it:C
$. 5. putchar(getchar());

<hat might this doF B7int- re;read the chapter a,out the pre;processor.C . /e write the statement in 8uestion %, assuming that putchar() and getchar() are macros.

3ssign#ents, %*$ressions and +$erators


Thinking in *. )orking things out. 5n operator is something which ta*es one or more values and does something useful with those values to produce a result. .t operates on them. The terminolog# of operators is the followingoperator 4omething which operates on someting. operand Each thing which is operated upon ,# an operator is called an operand. operation The action which was carried out upon the operands ,# the operator: There are lots of operators in C. 4ome of them ma# alread# ,e familiarP * ) = M ==

)ost operators can ,e thought of as ,elonging to one of three groups, divided up ar,itraril# according to what the# do with their operands. These rough groupings are thought of as follows

1perators which produce new values from old ones. The# ma*e a result from their operands. e.g. P, the addition operator ta*es two num,ers or two varia,les or a num,er and a varia,le and adds them together to give a new num,er. 1perators which ma*e comparisons. e.g. less than, e8ual to, greater than... 1perators which produce new varia,le t#pes- li*e the cast operator.

The ma?orit# of operators fall into the first group. .n fact the second group is a su,set of the first, in which the result of the operation is a ,oolean value of either true of false. C has no less than thirt# nine different operators. This is more than, sa#, Pascal and +54.C put together: The operators serve a variet# of purposes and the# can ,e used ver# freel#. The o,?ect of this chapter is to explain the ,asics of operators in C. The more a,struse operators are loo*ed at in another chapter.

Expressions and valuesExample %"1utput %"Parentheses and Priorit#-

Unar# 1perator Precedence4pecial 5ssignment 1perators PP --)ore 4pecial 5ssignmentsExample %G1utput %GThe Cast 1peratorExpressions and T#pes4ummar# of 1perators and Precedence>uestions %M-

%*$ressions and values


The most common operators in an# language are ,asic arithmetic operators. .n C these are the followingP P * ) ) '

plus Bunar#C minus Bforce value to ,e negativeC addition su,traction multiplication floating point division integer division DdivD integer remainder DmodD

These operators would not ,e useful without a partner operator which could attach the values which the# produce to varia,les. Perhaps the most important operator then is the assignment operator= assignment operator

This has ,een used extensivel# up to now. 2or exampledou%le x(y; x = $.58:; y = x; x = x P $ P 5)8;

The assignment operator ta*es the value of whatever is on the right hand side of the = s#m,ol and puts it into the varia,le on the left hand side. 5s usual there is some standard ?argon for this, which is useful to *now ,ecause compilers tend to use this when handing out error messages. The assignment operator can ,e summariAed in the following wa#-

lvalue = e(pression;

This statement sa#s no more than what has ,een said a,out assignments alread#- namel# that it ta*es something on the right hand side and attaches it to whatever is on the left hand side of the = s#m,ol. 5n e%pression is simpl# the name for an# string of operators, varia,les and num,ers. 5ll of the following could ,e called expressions# P $ P 5 a P somefunction() 5$ * x)5 i ' 7 x # ($$ P 7*(function() P $)) function () )* pro4ided it returns a sensi%le 4alue *)

8!alues on the other hand are simpl# names for memor# locations- in other words varia,le names, or identifiers. The name comes from Ileft values9 meaning an#thing which can legall# ,e written on the left hand side of an assignment.

%*a#$le
)**************************************) )* *) )* Gperators <emo - # *) )* *) )**************************************) -include .stdio.h/ )**************************************) main () 0 int i; printf (&1rithmetic Gperators2n2n&); i = :; printf (&i = :( -i is : 'd2n&( -i); printf (&int # P $ = 'd2n&( # P $); printf (&int 8 - # = 'd2n&( 8 - #); printf (&int 8 * $ = 'd2n&( 8 * $); printf (&2n> di4 7 = $ remainder #:2n&); printf (&int > ) 7 = 'd2n&( > ) 7); printf (&int > ' 7 = 'd2n&( > ' 7);

printf (&dou%le > ) 7 = 'f2n&( >.@ ) 7.@); A

+ut$ut
1rithmetic Gperators i = int int int :( -i # P $ 8 - # 8 * $ is : -: = 5 = 7 = #@

> di4 7 = $ remainder #: int > ) 7 = $ int > 7 = # dou%le > ) 7 = $.$8@@@@

Parentheses and Priorit,


Parentheses are classed as operators ,# the compiler, although their position is a ,it unclear. The# have a value in the sense that the# assume the value of whatever expression is inside them. Parentheses are used for forcing a priorit# over operators. .f an expression is written out in an am,iguous wa#, such asa P % ) 7 * $

it is not clear what is meant ,# this. .t could ,e interpreted in several wa#s((a P %) ) 7) * $

or
(a P %)) (7 * $)

or
a P (%)7) * $

and so on. +# using parentheses, an# dou,t a,out what the expression means is removed. Parentheses are said to have a higher priorit# than R N or E ,ecause the# are evaluated as Dsealed capsulesD ,efore other operators can act on them. Putting parentheses in ma# remove the am,iguit# of expressions, ,ut it does not alter than fact that
a P % ) 7 * $

is am,iguous. <hat will happen in this caseF The answer is that the C compiler has a convention a,out the wa# in which expressions are evaluated- it is called operator precedence. The convention is that some operators are stronger than others and that the stronger ones will alwa#s ,e evaluated first. 1therwise, expressions li*e the one a,ove are evaluated from left to right- so an expression will ,e dealt with from left to right unless a strong operator overrides this rule. Use parentheses to ,e sure. 5 ta,le of all operators and their priorities is given in the reference section.

&nar, +$erator Precedence


Unar# operators are operators which have onl# a single operand- that is, the# operate on onl# one o,?ect. 2or instancePP -P M

The precedence of unar# operators is from right to left so an expression li*e*ptrPP;

would do PP ,efore *.

/$ecial 3ssign#ent +$erators ++ and -C has some special operators which cut down on the amount of t#ping involved in a program. This is a su,?ect in which it ,ecomes important to thin* in C and not in other languages. The simplest of these perhaps are the increment and decrement operatorsPP --

increment- add one to decrement- su,tract one from

These attach to an# varia,le of integer or floating point t#pe. Bcharacter t#pes too, with care.C The# are used to simpl# add or su,tract % from a varia,le. Normall#, in other languages, this is accomplished ,# writing4aria%le = 4aria%le P #;

.n C this would also ,e 8uite valid, ,ut there is a much ,etter wa# of doing this4aria%lePP; or PP4aria%le;

would do the same thing more neatl#. 4imilarl#-

4aria%le = 4aria%le - #;

is e8uivalent to4aria%le--;

or
--4aria%le;

Notice particularl# that these two operators can ,e placed in front or after the name of the varia,le. .n some cases the two are identical, ,ut in the more advanced uses of C operators, which appear later in this ,oo*, there is a su,tle difference ,etween the two.

More /$ecial 3ssign#ents


7ere are some of the nicest operators in C. Li*e PP and -- these are short wa#s of writing longer expressions. Consider the statement4aria%le = 4aria%le P $5;

.n C this would ,e a long winded wa# of adding "G to 4aria%le. .t could ,e done more simpl# using the general increment operator- P=
4aria%le P= $5;

This performs exactl# the same operation. 4imilarl# one could write4aria%le# = 4aria%le# P 4aria%le$;

as
4aria%le# P= 4aria%le$;

and so on. There is a handful of these


.operation/=

operators- one for each of the ma?or operations which can ,e performed. There is, naturall#, one for su,traction too4aria%le = 4aria%le - 7$;

can ,e written-

4aria%le -= 7$;

)ore surprisingl#, perhaps, the multiplicative assignment4aria%le = 4aria%le * $;

ma# ,e written4aria%le *= $;

and so on. The main arithmetic operators all follow this patternP= -= *= )= '=

add assign su,tract assign multipl# assign divide Bdou,leC and BintC t#pes

remainder BintC t#pe onl#. and there are more exotic *inds, used for ,it operations or machine level operations, which will ,e ignored at this stage//= ..= Z= Q= M=

%*a#$le Listing
)**************************************) )* *) )* Gperators <emo - $ *) )* *) )**************************************) -include .stdio.h/ )**************************************) main () 0 int i; printf (&1ssignment Gperators2n2n&); i = #@; printf(&i = #@ : 'd2n&(i); )* 1ssignment *)

iPP; printf (&iPP : 'd2n&(i); i P= 8; printf (&i P= 8 : 'd2n&(i); i--; printf (&i-- : 'd2n&(i); i -= $; printf (&i -= $ : 'd2n&(i); i *= 8; printf (&i *= 8 :'d2n&(i); i )= $; printf (&i )= $ : 'd2n&(i); i '= 5; printf (&i ''= 5 : 'd2n&(i); A

)* i = i P # *) )* i = i P 8 *) )* i = i = # *) )* i = i - $ *) )* i = i * 8 *) )* i = i ) $ *) )* i = i ' 5 *)

+ut$ut
1ssignment Gperators i = #@ : #@ iPP : ## i P= 8 : #: i-- : #8 i -= $ : #5 i *= 8 ::8 i )= $ : 5$ i '= 5 : $

"he !ast +$erator


The cast operator is an operator which forces a particular t#pe mould or t#pe cast onto a value, hence the name. 2or instance a character t#pe varia,le could ,e forced to fit into an integer t#pe ,ox ,# the statementchar ch; int i; i = (int) ch;

This operator was introduced earlier, 4ee 3aria,les. .t will alwa#s produce some value, whatever the conversion- however remotel# impro,a,le it might seem. 2or instance it is 8uite possi,le to convert a character into a floating point num,er- the result will ,e a floating point representation of its 54C.. code:

%*$ressions and ",$es


There is a rule in C that all arithmetic and mathematical operations must ,e carried out with long varia,les- that is, the t#pes
dou%le long float int long int

.f the programmer tries to use other t#pes li*e short or float in a mathematical expression the# will ,e cast into long t#pes automaticall# ,# the compiler. This can cause confusion ,ecause the compiler will spot an error in the following statementshort i( U = $; i = U * $ P #;

5 compiler will claim that there is a t#pe mismatch ,etween i and the expression on the right hand side of the assignment. The compiler is perfectl# correct of course, even though it appears to ,e wrong. The su,tlet# is that arithmetic cannot ,e done in short t#pe varia,les, so that the expression is automaticall# converted into long t#pe or int t#pe. 4o the right hand side is int t#pe and the left hand side is short t#pe- hence there is indeed a t#pe mismatch. The programmer can get around this ,# using the cast operator to writeshort i( U = $; i = (short) U * $ P #;

5 similar thing would happen with floatfloat x( y = $.5; x = y * $.8;

would also ,e incorrect for the same reasons as a,ove. Comparisons and Logic

!o#$arisons and Logic

4ix operators in C are for ma*ing logical comparisons. The relevance of these operators will 8uic*l# ,ecome clear in the next chapter, which is a,out decisions and comparisons. The six operators which compare values are== I= / . /= .=

is e8ual to is not e8ual to is greater than is less than is greater than or e8ual to is less than or e8ual to

These operators ,elong to the second group according to the scheme a,ove ,ut the# do actuall# result in values so that the# could ,e thought of as ,eing a part of the first group of operators too. The values which the# produce are called true and false. 5s words, DtrueD and DfalseD are not defined normall# in C, ,ut it is eas# to define them as macros and the# ma# well ,e defined in a li,rar# file-define 3RUB # -define L1E+B @

2alsit# is assumed to have the value Aero in C and truth is represented ,# an# non;Aero value. These comparison operators are used for ma*ing decisions, ,ut the# are themselves operators and expressions can ,e ,uilt up with them.
# == #

has the value DtrueD Bwhich could ,e an#thing except AeroC. The statementint i; i = (# == $);

would ,e false, so i would ,e false. .n other words, i would ,e Aero. Comparisons are often made in pairs or even in groups and lin*ed together with words li*e 1/ and 5N6. 2or instance, some test might want to find out whether(' is greater than B) 'N) (' is greater than $)

C does not have words for these operations ,ut gives s#m,ols instead. The logical operators, as the# are called, are as follows-

MM QQ I

logical 5N6 logical 1/ inclusive logical N1T

The statement which was written in words a,ove could ,e translated as(1 / 9) MM (1 / D)

The statement(1 is greater than 9) 1N< (1 is not greater than D)

translates to(1 / 9) MM I(1 / D)

4ha*espeare might have ,een disappointed to learn that, whatever the value of a varia,le to%e the result of
theOuestion = to%e QQ Ito%e

must alwa#s ,e true. The N1T operator alwa#s creates the logical opposite- Itrue is false and Ifalse is true. 1n or the other of these must ,e true. theOuestion is therefore alwa#s true. 2ortunatel# this is not a matter of life or death:

/u##ar, of +$erators and Precedence


The highest priorit# operators are listed first.
"perator () XY PP -(type) * M [ I * ) ' "peration parentheses sOuare %rac6ets increment decrement cast operator the contents of the address of unary minus one"s complement logical NG3 multiply di4ide remainder (JG<) Evaluated. left to right left to right right right right right right right right right to to to to to to to to left left left left left left left left

left to right left to right left to right

P // .. / /= .= . == I= M Z Q MM QQ = P= -= *= )= '= //= ..= M= Z= Q=

add su%tract shift right shift left is greater than greater than or eOual to less than or eOual to less than is eOual to is not eOual to %itwise %itwise %itwise logical logical 1N< exclusi4e GR inclusi4e GR 1N< GR

left to right left to right left to right left to right left left left left to to to to right right right right

left to right left to right left left left left left right right right right right right right right right right right to to to to to to to to to to to to to to to to right right right right right left left left left left left left left left left left

assign add assign su%tract assign multiply assign di4ide assign remainder assign right shift assign left shift assign 1N< assign exclusi4e GR assign inclusi4e GR assign

(uestions
%. <hat is an operandF ". <rite a statement which prints out the remainder of H divided ,# ". G. <rite a short statement which assigns the remainder of H divided ,# " to a varia,le called DremD. . <rite a statement which su,tracts ;H from %!. H. <rite in C- if % is not e8ual to "G, print out DThan* goodness for mathematics:D

'ecisions
Testing and 9ranching. .aking conditions. 4uppose that a fictional traveller, some character in a ,oo* li*e this one, came to the end of a straight, unfinished road and waited there for the author to decide where the road would lead. The author might decide a num,er of things a,out this road and its traveller

The road will carr# on in a straight line. .f the traveller is thirst# he will stop for a drin* ,efore continuing.

The road will for* and the traveller will have to decide whether to ta*e the left ,ranch or the right ,ranch. The road might have a crossroads or a meeting point where man# roads come together. 5gain the traveller has to decide which wa# to go.

<e are often faced with this dilemma- a situation in which a decision has to ,e made. Up to now the simple example programs in this ,oo* have not had an# choice a,out the wa# in which the# progressed. The# have all followed narrow paths without an# choice a,out which wa# the# were going. This is a ver# limited wa# of expressing ideas though- the a,ilit# to ma*e decisions and to choose different options is ver# useful in programming. 2or instance, one might want to implement the following ideas in different programs

.f the user hits the ?ac*pot, write some message to sa# so. D=ou9ve won the game:D .f a ,an* ,alance is positive then print C for credit otherwise print 6 for de,it. .f the user has t#ped in one of five things then do something special for each special case, otherwise do something else.

These choices are actuall# ?ust the same choices that the traveller had to ma*e on his undecided path, thinl# disguised. .n the first case there is a simple choice- a do of don9t choice. The second case gives two choices- do thing % or thing ". The final choice has several possi,ilities. C offers four wa#s of ma*ing decisions li*e the ones a,ove. The# are listed here ,elow. The method which is num,ered ", was encountered in connection with the C preprocessor@ its purpose is ver# similar to "a.
#: if (somethingKisKtrue) 0 )* do something *) A if (somethingKisKtrue) 0 )* do one thing *) A else 0 )* do something else *) A V (somethingKisKtrue) : )* do one thing *) : )* do something else *) 5: switch (choice) 0 case firstKpossi%ility : )* do something *) case secondKpossi%ility : )* do something *)

$a:

$%:

.... A

if

ifexample f%if elseNested ifs and logicExample % 4tringing together if..elseswitchExample %HTo tr#-

The first form of the if statement is an all or nothing choice. if some condition is satisfied, do what is in the ,races, otherwise ?ust s*ip what is in the ,races. 2ormall#, this is writtenif (condition) statement;

or
if (condition) 0 compound statement A

Notice that, as well as a single statement, a whole ,loc* of statements can ,e written under the if statement. .n fact, there is an unwritten rule of thum, in C that wherever a single statement will do, a co$pound state$ent will do instead. 5 compound statement is a ,loc* of single statements enclosed ,# curl# ,races. 5 condition is usuall# some *ind of comparison, li*e the ones discussed in the previous chapter. .t must have a value which is either true or false B% or !C and it must ,e enclosed ,# the parentheses ( and ). .f the condition has the value Itrue9 then the statement or compound statement following the condition will ,e carried out, otherwise it will ,e ignored. 4ome of the following examples help to show thisint i; printf (&3ype in an integer&); scanf (&'ld&(Mi); if (i == @) 0 printf (&3he num%er was Nero&); A if (i / @) 0 printf (&3he num%er was positi4e&); A if (i . @) 0 printf (&3he num%er was negati4e&); A

The same code could ,e written more ,riefl#, ,ut perhaps less consistentl# in the following wa#int i; printf (&3ype in an integer&); scanf (&'ld&(Mi); if (i == @) printf (&3he num%er was Nero&); if (i / @) printf (&3he num%er was positi4e&); if (i . @) printf (&3he num%er was negati4e&);

The preference in this ,oo* is to include the ,loc* ,races, even when the# are not strictl# re8uired. This does no harm. .t is no more or less efficient, ,ut ver# often #ou will find that some extra statements have to go into those ,races, so it is as well to include them from the start. .t also has the appeal that it ma*es if statements loo* the same as all other ,loc* statements and it ma*es them stand out clearl# in the program text. This rule of thum, is onl# dropped in ver# simple examples li*eif (i == @) iPP;

The if statement alone allows onl# a ver# limited *ind of decision- it ma*es do or don9t decisions@ it could not decide for the traveller whether to ta*e the left for* or the right for* of his road, for instance, it could onl# tell him whether to get up and go at all. To do much more for programs it needs to ,e extended. This is the purpose of the else statement, descri,ed after some example listings..

%*a#$le Listings
)*****************************************) )* *) )* f... -# *) )* *) )*****************************************) -include .stdio.h/ -define 3RUB -define L1E+B # @

)******************************************) main () 0 int i; if (3RUB) 0 printf (&3his is always printed&);

A if (L1E+B) 0 printf (&3his is ne4er printed&); A A )*******************************************) )* *) )* f demo -$ *) )* *) )*******************************************) )* Gn %oard car computer. ?or6s out the *) )* num%er of 6ilometers to the litre *) )* that the car is doing at present *) -include .stdio.h/ )*******************************************) )* Ee4el @ *) )*******************************************) main () 0 dou%le fuel(distance; LindSalues (Mfuel(Mdistance); Report (fuel(distance); A )********************************************) )* Ee4el # *) )********************************************) LindSalues (fuel(distance) )* from car *)

)* 3hese 4alues would %e changing in *) )* a real car( independently of the *) )* program. *) dou%le *fuel(*distance; 0 )* how much fuel used since last chec6 on 4alues *) printf (&Bnter fuel used&); scanf (&'lf&(fuel); )* distance tra4elled since last chec6 on 4alues *) printf (&Bnter distance tra4elled&); scanf (&'lf&(distance); A )**********************************************)

Report (fuel(distance) dou%le fuel(distance; 0 dou%le 6pl; 6pl = distance)fuel;

)* on dash%oard *)

printf (&fuel consumption: '$.#lf&(6pl); printf (& 6ilometers per litre2n&); if (6pl .= #) 0 printf (&,redict fuel lea6 or car&); printf (& needs a ser4ice2n&); A if (distance / 8@@) 0 printf (&Remem%er to chec6 tyres2n&); A if (fuel / 5@) )* 3an6 holds 7@ l *) 0 printf (&Luel getting low: 's left2n&(7@-fuel); A A if

... else

The if .. else statement has the formif (condition) statement1; else statement2;

This is most often written in the compound statement formif (condition) 0 statements A else 0 statements A

The if..else statement is a two wa# ,ranch- it means do one thing or the other. <hen it is executed, the condition is evaluated and if it has the value Itrue9 Bi.e. not AeroC then state$ent1 is executed. .f the condition is Ifalse9 Bor AeroC then state$ent: is executed. The if..else construction often saves an unnecessar# test from having to ,e made. 2or instanceint i;

scanf (&'ld&(i); if (i / @) 0 printf (&3hat num%er was positi4eI&); A else 0 printf (&3hat num%er was negati4e or NeroI&); A

.t is not necessar# to test whether i was negative in the second ,loc* ,ecause it was implied ,# the if..else structure. That is, that ,loc* would not have ,een executed unless i were N1T greater than Aero. The wear# traveller a,ove might ma*e a decision such asif (rightleg / leftleg) 0 ta6eKleftK%ranch(); A else 0 ta6eKrightK%ranch(); A

6ested ifs and logic


Consider the following statements which decide upon the value of some varia,le i. Their purposes are exactl# the same.
if ((i / $) MM (i . 7)) 0 printf (&i is three&); A

or-

if (i / $) 0 if (i . 7) 0 printf (&i is three&); A A

+oth of these test i for the same information, ,ut the# do it in different wa#s. The first method might ,een ,orn out of the following se8uence of thought-

.f i is greater than " and i is less than four, ,oth at the same time, then i has to ,e G. The second method is more complicated. Thin* carefull#. .t sa#s.f i is greater than ", do what is in the curl# ,races. .nside these curl# ,races i is alwa#s greater than " ,ecause otherwise the program would never have arrived inside them. Now, if i is also less than , then do what is inside the new curl# ,races. .nside these curl# ,races i is alwa#s less than . +ut wait: The whole of the second test is held inside the Di is greater than "D ,races, which is a sealed capsule- nothing else can get in, so, if the program gets into the Di is less than D ,races as well, then ,oth facts must ,e true at the same time. There is onl# one integer which is ,igger than " and less than at the same time- it is G. 4o i is G. The aim of this demonstration is to show that there are two wa#s of ma*ing multiple decisions in C. Using the logical comparison operators MM, QQ B5N6,1/C and so on.. several multiple tests can ,e made. .n man# cases though it is too difficult to thin* in terms of these operators and the sealed capsule idea ,egins to loo* attractive. This is

another advantage of using the curl# ,races- it helps the programmer to see that if statements and if..else statements are made up of sealed capsule parts. 1nce inside a sealed capsule
if (i / $) 0 )* i is greater than $ in hereI *) A else 0 )* i is not greater than $ hereI *) A

the programmer can rest assured that nothing illegal can get in. The ,loc* ,races are li*e regions of grace- the# cannot ,e penetrated ,# an#thing which does not satisf# the right conditions. This is an enourmous weight off the mind: The programmer can sit ,ac* and thin*- . have accepted that i is greater than " inside these ,races, so . can stop worr#ing a,out that now. This is how programmers learn to thin* in a structured wa#. The# learn to ,e satisfied that certain things have alread# ,een proven and thus save themselves from the onset of madness as the ideas ,ecome too complex to thin* of all in one go.

%*a#$le Listing
)***********************************************) )* *) )* f demo -5 *) )* *) )***********************************************) -include .stdio.h/ )***********************************************) main () 0 int persnum(usernum(%alance; persnum = ;7:$; %alance = -#$; printf (&3he ,lastic 9an6 Dorporation2n&); printf (&,lease enter your personal num%er :&); usernum = getnum%er(); if (usernum == ;7:$) 0 printf (&2n3he current state of your account2n&); printf (&is 'd2n&(%alance); if (%alance . @) 0 printf (&3he account is o4erdrawnI2n&); A

A else 0 printf (&3his is not your account2n&); A printf (&Ha4e a splendid dayI 3han6 you.2n&); A )**************************************************) getnum%er () 0 int num = @; scanf (&'d&(Mnum); if ((num / >>>>) QQ (num .= @)) 0 printf (&3hat is not a 4alid num%er2n&); A return (num); A )* get a num%er from the user *)

/tringing together if..else


<hat is the difference ,etween the following programsF The# ,oth interpret some imaginar# exam result in the same wa#. The# ,oth loo* identical when compiled and run. <h# then are the# differentF
)**************************************************) )* ,rogram # *) )**************************************************) -include .stdio.h/ main () 0 int result; printf(&3ype in exam result&); scanf (&'d&(Mresult); if (result . #@) 0 printf (&3hat is poor&); A if (result / $@) 0 printf (&\ou ha4e passed.&); A if (result / ;@) 0

printf (&\ou got an 1I&); A A )* end *) )**************************************************) )* ,rogram $ *) )**************************************************) -include .stdio.h/ main () 0 int result; printf(&3ype in exam result&); scanf (&'d&(Mresult); if (result . #@) 0 printf (&3hat is poor&); A else 0 if (result / $@) 0 printf (&\ou ha4e passed.&); A else 0 if (result / ;@) 0 printf (&\ou got an 1I&); A A A A

The answer is that the second of these programs can ,e more efficient. This ,ecause it uses the else form of the if statement which in turn means that few things have to ,e calculated. Program one ma*es ever# single test, ,ecause the program meets ever# if statement, one after the other. The second program does not necessaril# do this however. The nested if statements ma*e sure that the second two tests are onl# made if the first one failed. 4imilarl# the third test is onl# performed if the first two failed. 4o the second program could end up doing a third of the wor* of the first program, in the ,est possi,le case. Nesting decisions li*e this can ,e an efficient wa# of controlling long lists of decisions li*e those a,ove. Nested loops ma*e a program ,ranch into lots of possi,le paths, ,ut choosing one path would preclude others.

switch

4 integers and characters

The switch construction is another wa# of ma*ing a program path ,ranch into lots of different lim,s. .t can ,e used as a different wa# of writing a string of if .. else statements, ,ut it is more versatile than that and it onl# wor*s for integers and character t#pe values. .t wor*s li*e a *ind of multi;wa# switch. B4ee the diagram.C The switch statement has the following formswitch (int or char e(pression) 0 case constant : statement; %rea6; ... A

)* optional *)

.t has an expression which is evaluated and a num,er of constant Icases9 which are to ,e chosen from, each of which is followed ,# a statement or compound statement. 5n extra statement called %rea6 can also ,e incorporated into the ,loc* at an# point. %rea6 is a

reserved word.

The switch statement can ,e written more specificall# for integersswitch (integer value) 0 case #: case $: .... default: default statement %rea6; A )* optional line *) statement1; %rea6; statement2; %rea6;

)* optional line *) )* optional line *)

<hen a switch statement is encountered, the expression in the parentheses is evaluated and the program chec*s to see whether the result of that expression matches an# of the constants la,elled with case. .f a match is made Bfor instance, if the expression is evaluated to "G and there is a statement ,eginning Dcase "G - ...DC execution will start ?ust after that case statement and will carr# on until either the closing ,race A is encountered or a ,rea* statement is found. %rea6 is a hand# wa# of ?umping straight out of the switch ,loc*. 1ne of the cases is called default. 4tatements which follow the default case are executed for all cases which are not specificall# listed. switch is a wa# of choosing some action from a num,er of *nown instances. Loo* at the following example.

%*a#$le Listing
)************************************************) )* *) )* switch .. case *) )* *) )************************************************) )* Jorse code program. Bnter a num%er and *) )* find out what it is in Jorse code *) -include .stdio.h/ -define DG<B @ )*************************************************) main () 0 short digit; printf (&Bnter any digit in the range @..>&); scanf (&'h&(Mdigit); if ((digit . @) QQ (digit / >)) 0

printf (&Num%er was not in range @..>&); return (DG<B); A printf (&3he Jorse code of that digit is &); Jorse (digit); A )************************************************) Jorse (digit) short digit; 0 switch (digit) 0 case @ : printf %rea6; case # : printf %rea6; case $ : printf %rea6; case 5 : printf %rea6; case 7 : printf %rea6; case 8 : printf %rea6; case : : printf %rea6; case ; : printf %rea6; case = : printf %rea6; case > : printf A A )* print out Jorse code *)

(&-----&); (&.----&); (&..---&); (&...--&); (&....-&); (&.....&); (&-....&); (&--...&); (&---..&); (&----.&);

The program selects one of the printf statements using a switch construction. 5t ever# case in the switch, a %rea6 statement is used. This causes control to ?ump straight out of the switch statement to its closing ,race A. .f ,rea* were not included it would go right on executing the statements to the end, testing the cases in turn. ,rea* this gives a wa# of ?umping out of a switch 8uic*l#. There might ,e cases where it is not necessar# or not desira,le to ?ump out of the switch immediatel#. Thin* of a function yes() which gets a character from the user and tests whether it was 9#9 or 9=9.
yes () )* 1 sloppy %ut simple function *)

0 switch (getchar()) 0 case "y" :

case "\" : return 3RUB default : return L1E+B A

.f the character is either 9#9 or 9=9 then the function meets the statement return 3RUB. .f there had ,een a ,rea* statement after case 9#9 then control would not have ,een a,le to reach case 9=9 as well. The return statement does more than ,rea* out of switch, it ,rea*s out of the whole function, so in this case ,rea* was not re8uired. The default option ensures that whatever else the character is, the function returns false.

"hings to tr,
%. <rite a program to get a lot of num,ers from the user and print out the maximum and minimum of those. ". Tr# to ma*e a counter which is reset to Aero when it reaches &&&&. G. Tr# to write a program incorporating the statement if (yes()) 0...A.

Loo$s
*ontrolling repetiti!e processes. 0esting loops 6ecisions can also ,e used to ma*e up loops. Loops free a program from the strait?ac*et of doing things onl# once. The# allow the programmer to ,uild a se8uence of instructions which can ,e executed again and again, with some condition deciding when the# will stop. There are three *inds of loop in C. The# are called while do ... while for

These three loops offer a great amount of flexi,ilit# to programmers and can ,e used in some surprising wa#s:
while

whileExample %MExample %(do whileExample %'forThe flexi,le for loop>uitting Loops and 7urr#ing Them Up:Nested Loops>uestions %'-

The simplest of the three loops is the while loop. .n common language while has a fairl# o,vious meaning- the while;loop has a conditionwhile (condition) 0 statements; A

and the statements in the curl# ,races are executed while the condition has the value DtrueD B % C. There are dialects of English, however, in which DwhileD does not have its commonplace meaning, so it is worthwhile explaining the steps which ta*e place in a

while loop. The first important thing a,out this loop is that has a conditional expression Bsomething li*e (a / %) etc...C which is evaluated ever# time the loop is executed ,# the computer. .f the value of the expression is true, then it will carr# on with the instructions in the curl# ,races. .f the expression evaluates to false Bor !C then the instructions in the ,races are ignored and the entire while loop ends. The computer then moves onto the next statement in the program. The second thing to notice a,out this loop is that the conditional expression comes at the start of the loop- this means that the condition is tested at the start of ever# Ipass9, not at the end. The reason that this is important is this- if the condition has the value false ,efore the loop has ,een executed even once, the statements inside the ,races will not get executed at all ; not even once. The ,est wa# to illustrate a loop is to give an example of its use. 1ne example was snea*ed into an earlier chapter ,efore its time, in order to write the s6ipgar%() function which complemented scanf(). That wass6ipgar% () )* s6ip gar%age corrupting scanf *)

0 while (getchar() I= "2n") 0 A

This is a slightl# odd use of the while loop which is pure C, through and through. .t is one instance in which the programmer has to start thin*ing C and not an# other language. 4omething which is immediatel# o,vious from listing is that the while loop in s6ipgar%() is empt#- it contains no statements. This is 8uite valid- the loop will merel# do nothing a certain num,er of times... at least it would do nothing if it were not for the assignment in the conditional expression: .t could also ,e writtens6ipgar% () )* s6ip gar%age corrupting scanf *)

0 while (getchar() I= "2n") 0 A A

The assignment inside the conditional expression ma*es this loop special. <hat happens is the following. <hen the loop is encountered, the computer attempts to evaluate the expression inside the parentheses. There, inside the parentheses, it finds a function call to getchar(), so it calls getchar() which fetches the next character from the input. getchar() then ta*es on the value of the character which it fetched from the input file. Next the computer finds the I= Dis not e8ual toD s#m,ol and the newline character 2n. This means that there is a comparison to ,e made. The computer compares the character fetched ,# getchar() with the newline character and if the# are Inot e8ual9 the expression is true. .f the# are e8ual the expression is false. Now, if the expression is true, the while statement will loop and start again ; and it will evaluate the expression on ever# pass of the loop to chec* whether or not it is true. <hen the expression eventuall# ,ecomes false the loop will 8uit. The net result of this su,tlet# is that s6ipgar%() s*ips all the input characters up to and including the next newline 2n character and that usuall# means the rest of the input.

%*a#$le Listing
5nother use of while is to write a ,etter function called yes(). The idea of this function was introduced in the previous section. .t uses a while loop which is alwa#s true to repeat the process of getting a response from the user. <hen the response is either #es or no it 8uits using the return function to ?ump right out of the loop.
)***********************************************) )* *) )* Ri4e me your answerI *) )* *) )***********************************************) -include .stdio.h/ -define 3RUB -define L1E+B # @

)*************************************************) )* Ee4el @ *) )*************************************************) main () 0 printf (&\es or noV (\)N)2n&); if (yes()) 0 printf (&\B+I&); A else 0 printf (&NGI&); A A )*************************************************) )* Ee4el # *) )*************************************************) yes () 0 char get6ey(); while (true) 0 switch (get6ey()) 0 case "y" : case "\" : return (3RUB); case "n" : case "N" : return (L1E+B); A A A )*************************************************) )* 3ool6it *) )*************************************************) char get6ey () 0 char ch; ch = getchar(); s6ipgar%(); A )**************************************************) s6ipgar% () 0 while (getchar() I= "2n") 0 A )* get a character P RB3URN *) )* get response \)N Ouery *)

A )* end *)

%*a#$le Listing
This example listing prompts the user to t#pe in a line of text and it counts all the spaces in that line. .t 8uits when there is no more input left and printf out the num,er of spaces.
)***********************************************) )* *) )* while loop *) )* *) )***********************************************) )* count all the spaces in an line of input *) -include .stdio.h/ main () 0 char ch; short count = @; printf (&3ype in a line of text2n&); while ((ch = getchar()) I= "2n") 0 if (ch == " ") 0 countPP; A A printf (&Num%er of space = 'd2n&(count); A do while

..

The do..while loop resem,les most closel# the repeat..until loops of Pascal and +54.C except that it is the Ilogical opposite9. The do loop has the formdo 0 statements; A

while (condition)

Notice that the condition is at the end of this loop. This means that a do..while loop will alwa#s ,e executed at least once, ,efore the test is made to determine whether it should continue. This is the onl# difference ,etween while and do..while. 5 do..while loop is li*e the Drepeat .. untilD of other languages in the following sense- if the condition is N1Ted using the I operator, then the two are identical.
repeat == until(condition) while (Icondition) do

This fact might ,e useful for programmers who have not #et learned to thin* in C:

%*a#$le Listing
7ere is an example of the use of a do..while loop. This program gets a line of input from the user and chec*s whether it contains a string mar*ed out with && 8uote mar*s. .f a string is found, the program prints out the contents of the string onl#. 5 t#pical input line might ,e"nceupon a time *+ere !e go round the&&&*!hat a terrible&&

The output would then ,e+ere !e go round the&&&

.f the string has onl# one 8uote mar* then the error message Istring was not closed ,efore end of line9 will ,e printed.
)**********************************************) )* *) )* do .. while demo *) )* *) )**********************************************)

)* print a string enclosed %y Ouotes & & *) )* gets input from stdin i.e. 6ey%oard *) )* s6ips anything outside the Ouotes *) -include .stdio.h/ )*************************************************) )* Ee4el @ *) )*************************************************) main () 0 char ch(s6ipstring(); do 0 if ((ch = getchar()) == "&") 0 printf (&3he string was:2n&); ch = s6ipstring(); A A

while (ch I= "2n") 0 A A )*************************************************) )* Ee4el # *) )*************************************************) char s6ipstring () )* s6ip a string &...& *) 0 char ch; do 0 ch = getchar(); putchar(ch); if (ch == "2n") 0 printf (&2n+tring was not closed &); printf (&%efore end of line2n&); %rea6; A A while (ch I= "&") 0 A return (ch); A for

The most interesting and also the most difficult of all the loops is the for loop. The name for is a hangover from earlier da#s and other languages. .t is not altogether appropriate for C9s version of for. The name comes from the t#pical description of a classic for loop2or all values of !ariable from !alue1 to !alue: in steps of 4alue5, repeat the following se8uence of commands.... .n +54.C this loo*s li*eLGR variable = value1 3G value2 +3B, value, NBC3 variable

The C for loop is much more versatile than its +54.C counterpart@ it is actuall# ,ased upon the while construction. 5 for loop normall# has the characteristic feature of controlling one particular varia,le, called the control varia,le. That varia,le is somehow associated with the loop. 2or example it might ,e a varia,le which is used to count Dfor values from ! to %!D or whatever. The form of the for loop isfor (statement1; condition; statement2) 0 A

2or normal usage, these expressions have the following significance. state$ent1 This is some *ind of expression which initialiAes the control varia,le. This statement is onl# carried out once ,efore the start of the loop. e.g. i = @; condition This is a condition which ,ehaves li*e the while loop. The condition is evaluated at the ,eginning of ever# loop and the loop is onl# carried out while this expression is true. e.g. i . $@; state$ent: This is some *ind of expression for altering the value of the control varia,le. .n languages such as Pascal this alwa#s means adding or su,tracting % from the varia,le. .n C it can ,e a,solutel# an#thing. e.g. iPP or i *= $@ or i )= $.5 ... Compare a C for loop to the +54.C for loop. 7ere is an example in which the loop counts from ! to %! in steps of !.HLGR C = @ 3G #@ +3B, @.8 NBC3 C for (x = @; x .= #@; x P= @.8) 0 A

The C translation loo*s peculiar in comparison ,ecause it wor*s on a su,tl# different principle. .t does not contain information a,out when it will stop, as the +54.C one does, instead it contains information a,out when it should ,e looping. The result is that a C for loop often has the .= s#m,ol in it. The for loop has plent# of uses. .t could ,e used to find the sum of the first n natural num,ers ver# simpl#sum = @; for (i = @; i .= n; iPP) 0 sum P= i; A

.t generall# finds itself useful in applications where a single varia,le has to ,e controlled in a well determined wa#. g

%*a#$le Listing
This example program prints out all the primes num,ers ,etween % and the macro value maxint. Prime num,ers are num,ers which cannot ,e divided ,# an# num,er except % without leaving a remainder.
)************************************************) )* *) )* ,rime Num%er Renerator -# *) )* *) )************************************************) )* )* )* )* Dhec6 for prime num%er %y raw num%er crunching. 3ry di4iding all num%ers up to half the siNe of a gi4en i( if remainder == @ then not primeI *) *) *) *)

-include .stdio.h/ -define J1C N3 -define 3RUB -define L1E+B 8@@ # @

)*************************************************) )* Ee4el @ *) )*************************************************) main () 0 int i; for (i = $; i .= J1C N3; iPP) 0 if (prime(i)) 0 printf (&'8d&(i); A

)*************************************************) )* Ee4el # *) )*************************************************) prime (i) int i; 0 int U; for (U = $; U .= i)$; UPP) 0 if (i ' U == @) 0 return L1E+B; A A return 3RUB; A )* chec6 for a prime num%er *)

"he fle*i le for loo$


The word Istatement9 was chosen carefull#, a,ove, to descri,e what goes into a for loop. Loo* at the loop againfor (statement1; condition; statement2) 0 A

4tatement reall# means what it sa#s. C will accept an# statement in the place of those a,ove, including the empt# statement. The while loop could ,e written as a for loop:
for (; condition; ) 0 A )* while VV *)

7ere there are two empt# statements, which are ?ust wasted. This flexi,ilit# can ,e put to ,etter uses though. Consider the following loopfor (x = $; x .= #@@@; x = x * x) 0 .... A

This loop ,egins from " and each time the statements in the ,races are executed x s8uares itself: 5nother odd loo*ing loop is the following onefor (ch = "*"; ch I= "2n"; ch = getchar()) 0 A

This could ,e used to ma*e #et another different *ind of s6ipgar%() function. The loop starts off ,# initialiAing ch with a star character. .t chec*s that ch I= "2n" Bwhich it isn9t, first time aroundC and proceeds with the loop. 1n each new pass, ch is reassigned ,# calling the function getchar(). .t is also possi,le to com,ine several incremental commands in a loopfor (i = @( U=#@; i . U; iPP( U--) 0 printf(&i = 'd( U= 'd2n&(i(U); A

State$ent: can ,e an# statement at all which the programmer would li*e to ,e executed on ever# pass of the loop. <h# not put that statement in the curl# ,racesF .n most cases that would ,e the ,est thing to do, ,ut in special instances it might *eep a program tidier or more reada,le to put it in a for loop instead. There is no good rule for when to do this, except to sa#- ma*e #ou code as clear as possi,le. .t is not onl# the statements which are flexi,le. 5n unnerving feature of the for construction Baccording to some programmersC is that even the conditional expression in the for loop can ,e altered ,# the program from within the loop itself if is written as a varia,le.
int i( num%er = $@; for (i = @; i .= num%er; iPP) 0 if (i == >) 0 num%er = 5@; A A

This is so nerve shattering that man# languages for,id it outright. To ,e sure, is not often a ver# good idea to use this facilit#, ,ut in the right hands, it is a powerful one to have around.

(uitting Loo$s and Hurr,ing "he# &$7


C provides a simple wa# of ?umping out of an# of the three loops a,ove at an# stage, whether it has finished or not. The statement which performs this action is the same statement which was used to ?ump out of switch statements in last section.
%rea6;

.f this statement is encountered a loop will 8uit where it stands. 2or instance, an expensive wa# of assigning i to ,e %" would ,e-

for (i = #; i .= $@; iPP) 0 if (i == #$) 0 %rea6; A A

4till another wa# of ma*ing s6ipgar%() would ,e to perform the following loopwhile (3RUB) 0 ch = getchar(); if (ch == "2n") 0 %rea6; A A

1f course, another wa# to do this would ,e to use the return() statement, which ?umps right out of a whole function. %rea6 onl# ?umps out of the loop, so it is less drastic. 5s well as wanting to 8uit a loop, a programmer might want to hurr# a loop on to the next pass- perhaps to avoid executing a lot of irrelevant statements, for instance. C gives a statement for this too, calledcontinue;

<hen a continue statement is encountered, a loop will stop whatever it is doing and will go straight to the start of the next loop pass. This might ,e useful to avoid dividing ,# Aero in a programfor (i = -#@; i .= #@; iPP) 0 if (i == @) 0 continue; A printf (&'d&( $@)i); A

6ested Loo$s
Li*e decisions, loops will also nest- that is, loops can ,e placed inside other loops. 5lthough this feature will wor* with an# loop at all, it is most commonl# used with the for loop, ,ecause this is easiest to control. The idea of nested loops is important for multi; dimensional arra#s which are examined in the next section. 5 for loop controls the num,er of times that a particular set of statements will ,e carried out. 5nother outer loop could ,e used to control the num,er of times that a whole loop is carried out. To see the ,enefit of nesting loops, the example ,elow shows how a s8uare could ,e printed out using two printf statements and two loops.

)*****************************************) )* *) )* 1 &+Ouare& *) )* *) )*****************************************) -include .stdio.h/ -define + FB #@

)*****************************************) main () 0 int i(U; for (i = #; i .= + FB; iPP) 0 for (U = #; U .= + FB; UPP) 0 printf(&*&); A printf (&2n&); A A

The output of this program is a D*ind ofD s8uare********** ********** ********** ********** ********** ********** ********** ********** ********** **********

(uestions
%. ". G. . H. 7ow man# *inds of loop does C offer, and what are the#F <hen is the condition tested in each of the loopsF <hich of the loops is alwa#s executed onceF <rite a program which copies all input to output line ,# line. <rite a program to get %! num,ers from the user and add them together.

3rra,s
;ows and tables of storage.

5rra#s are a convenient wa# of grouping a lot of varia,les under a single varia,le name. 5rra#s are li*e pigeon holes or chess,oards, with each compartment or s8uare acting as a storage place@ the# can ,e one dimensional, two dimensional or more dimensional: 5n arra# is defined using s8uare ,rac*ets XY. 2or example- an arra# of three integers called DtripletD would ,e declared li*e thisint tripletX5Y;

Notice that there is no space ,etween the s8uare ,rac*et X and the name of the arra#. This statement would cause space for three integers t#pe varia,les to ,e created in memor# next to each other as in the diagram ,elow.
int triplet: Q -----------------------------------Q Q Q ------------------------------------

The num,er in the s8uare ,rac*ets of the declaration is referred to as the Iindex9 BpluralindiciesC or Isu,script9 of the arra# and it must ,e an integer num,er ,etween ! and Bin this caseC ". The three integers are called elements of the arra# and the# are referred to in a program ,# writingtripletX@Y tripletX#Y tripletX$Y

Note that the indicies start at Aero and run up to one less than the num,er which is placed in the declaration Bwhich is called the dimension of the arra#.C The reason for this will ,ecome clear later. 5lso notice that ever# element in an arra# is of the same t#pe as ever# other. .t is not Bat this stageC possi,le to have arra#s which contain man# different data t#pes. <hen arra#s are declared inside a function, storage is allocated for them, ,ut that storage space is not initialiAed- that is, the memor# space contains gar,age Brandom valuesC. .t is usuall# necessar#, therefore, to initialiAe the arra# ,efore the program trul# ,egins, to prepare it for use. This usuall# means that all the elements in the arra# will ,e set to Aero.

<h# use arra#sFLimits and The 6imension of an arra#5rra#s and for loopsExample %&5rra#s 1f )ore Than 1ne 6imension5rra#s and Nested LoopsExample "!1utput of Game of Life.nitialiAing 5rra#s5rra#s and Pointers5rra#s as Parameters-

>uestions %&-

1h, use arra,s8


5rra#s are most useful when the# have a large num,er of elements- that is, in cases where it would ,e completel# impractical to have a different name for ever# storage space in the memor#. .t is then highl# ,eneficial to move over to arra#s for storing information for two reasons

The storage spaces in arra#s have indicies. These num,ers can often ,e related to varia,les in a pro,lem and so there is a logical connection to ,e made ,etween an arra# an a program. .n C, arra#s can ,e initialiAed ver# easil# indeed. .t is far easier to initialiAe an arra# than it is to initialiAe twent# or so varia,les.

The first of these reasons is pro,a,l# the most important one, as far as C is concerned, since information can ,e stored in other wa#s with e8uall# simple initialiAation facilities in C. 1ne example of the use of an arra# might ,e in ta*ing a census of the t#pes of car passing on a road. +# defining macros for the names of the different cars, the# could easil# ,e lin*ed to the elements in an arra#.
3ype car auto %il 1rray Blement @ # $

The arra# could then ,e used to store the num,er of cars of a given t#pe which had driven past. e.g.
)***********************************************) )* *) )* Densus *) )* *) )***********************************************) -include .stdio.h/ -define -define -define -define NG3L N +HB< # D1R @ 1U3G # 9 E $

)************************************************) main () 0 int typeX5Y; int index; for (index = @; index . 5; indexPP) 0

typeXindexY = @; A while (NG3L N +HB<) 0 printf (&Bnter type num%er @(#( or $&); scanf (&'d&( Mindex); s6ipgar%(); typeXindexY P= #; A )* +ee text %elow *)

This program, first of all, initialiAes the elements of the arra# to ,e Aero. .t then enters a loop which repeatedl# fetches a num,er from the user and increases the value stored in the arra# element, la,elled ,# that num,er, ,# %. The effect is to count the cars as the# go past. This program is actuall# not a ver# good program for two reasons in particular

2irstl#, it does not chec* that the num,er which the user t#ped is actuall# one of the elements of the arra#. B4ee the section ,elow a,out this.C The loop goes on for ever and the program never gives up the information which is stores. .n short- it is not ver# useful.

5nother example, which comes readil# to mind, would ,e the use of a two dimensional arra# for storing the positions of chess pieces in a chess game. Two dimensional arra#s have a chess,oard;li*e structure alread# and the# re8uire two num,ers Btwo indiciesC to pinpoint a particular storage cell. This is ?ust li*e the num,ers on chess ,oard, so there is an immediate and logical connection ,etween an arra# and the pro,lem of *eeping trac* of the pieces on a chess ,oard. 5rra#s pla# an important role in the handling of string varia,les. 4trings are important enough to have a section of their own, 4ee 4trings.

Li#its and "he 'i#ension of an arra,


C does not do much hand holding. .t is invaria,l# up to the programmer to ma*e sure that programs are free from errors. This is especiall# true with arra#s. C does not complain if #ou tr# to write to elements of an arra# which do not exist: 2or examplechar arrayX8Y;

is an arra# with H elements. .f #ou wrotearrayX;Y = "*";

C would happil# tr# to write the character * at the location which would have corresponded to the seventh element, had it ,een declared that wa#. Unfortunatel# this would pro,a,l# ,e memor# ta*en up ,# some other varia,le or perhaps even ,# the operating s#stem. The result would ,e either

The value in the incorrect memor# location would ,e corrupted with unpredicta,le conse8uences.

The value would corrupt the memor# and crash the program completel#: 1n Unix s#stems this leads to a memor# seg$entation fault.

The second of these tends to ,e the result on operating s#stems with proper memor# protection. <riting over the ,ounds of an arra# is a common source of error. /emem,er that the arra# limits run from Aero to the siAe of the arra# minus one.

3rra,s and for loo$s


5rra#s have a natural partner in programs- the for loop. The for loop provides a simple wa# of counting through the num,ers of an index in a controlled wa#. Consider a one dimensional arra# called array. 5 for loop can ,e used to initialiAe the arra#, so that all its elements contain Aero-define + FB main () 0 int i( arrayX+ FBY; for (i = @; i . + FB; iPP) 0 arrayXiY = @; A A #@;

.t could e8uall# well ,e used to fill the arra# with different values. Consider-define + FB main () 0 int i( arrayXsiNeY; for (i = @; i . siNe; iPP) 0 arrayXiY = i; A A #@;

This fills each successive space with the num,er of its indexindex element contents @ # $ 5 7 8 : ; = >

--------------------------------------Q @ Q # Q $ Q 5 Q 7 Q 8 Q : Q ; Q = Q > Q ---------------------------------------

The for loop can ,e used to wor* on an arra# se8uentiall# at an# time during a program, not onl# when it is ,eing initialiAed. The example listing ,elow shows an example of how this might wor* for a one dimensional arra#, called an Eratosthenes sieve. This sieve is an arra# which is used for weeding out prime num,ers, that is- num,ers which cannot ,e divided ,# an# num,er except % without leaving a remainder or a fraction. .t wor*s ,# filling an arra# with num,ers from ! to some maximum value in the same wa# that was shown a,ove and then ,# going through the num,ers in turn and deleting Bsetting e8ual to AeroC ever# multiple of ever# num,er from the arra#. This eliminates all the num,ers which could ,e divided ,# something exactl# and leaves onl# the prime num,ers at the end. Tr# to follow the listing ,elow.

%*a#$le Listing
)******************************************************) )* *) )* ,rime Num%er +ie4e *) )* *) )******************************************************) -include .stdio.h/ -define + FB -define <BEB3B< 8@@@ @

)*******************************************************) )* Ee4el @ *) )*******************************************************) main () 0 short sie4eX+ FBY; printf (&Bratosthenes +ie4e 2n2n&); Lill+ei4e(sie4e); +ort,rimes(sie4e); ,rint,rimes(sie4e); A )*********************************************************) )* Ee4el # *) )*********************************************************) Lill+ei4e (sie4e) short sie4eX+ FBY; 0 short i; for (i = $; i . + FB; iPP) 0 sie4eXiY = i; A A )* Lill with integers *)

)**********************************************************) +ort,rimes (sie4e) short sie4eX+ FBY; 0 short i; for (i = $; i . + FB; iPP) 0 if (sie4eXiY == <BEB3B<) 0 continue; A <eleteJultiplesGf(i(sie4e); A A )***********************************************************) ,rint,rimes (sie4e) short sie4eX+ FBY; 0 short i; for (i = $; i . + FB; iPP) 0 if (sie4eXiY == <BEB3B<) 0 continue; A else 0 printf (&'8d&(sie4eXiY); A A A )***********************************************************) )* Ee4el $ *) )***********************************************************) <eleteJultiplesGf (i(sie4e) short i(sie4eX+ FBY; 0 short U( mult = $; for (U = i*$; U . + FB; U = i * (multPP)) 0 sie4eXUY = <BEB3B<; A A )* end *) )* <elete.. of an integer *) )* ,rint out array *) )* <elete non primes *)

3rra,s +f More "han +ne 'i#ension


There is no limit, in principle, to the num,er of indicies which an arra# can have. BThough there is a limit to the amount of memor# availa,le for their storage.C 5n arra# of two dimensions could ,e declared as followsfloat num%ersX+ FBYX+ FBY;

is some constant. BThe siAes of the two dimensions do not have to ,e the same.C This is called a two dimensional arra# ,ecause it has two indicies, or two la,els in s8uare ,rac*ets. .t has B+ FB N + FBC or siAe;s8uared elements in it, which form an imaginar# grid, li*e a chess ,oard, in which ever# s8uare is a varia,le or storage area.
+ FB -----------------------------------Q @ Q # Q $ Q 5 Q 7 Q 8 Q : Q ; Q = Q ... (up to + FB) -----------------------------------Q # Q Q Q Q Q Q Q Q Q -----------------------------------Q $ Q Q Q Q Q Q Q Q Q -----------------------------------Q 5 Q Q Q Q Q Q Q Q Q -----------------------------------Q 7 Q Q Q Q Q Q Q Q Q -----------------------------------Q 8 Q Q Q Q Q Q Q Q Q -----------------------------------Q : Q Q Q Q Q Q Q Q Q -----------------------------------Q ; Q Q Q Q Q Q Q Q Q -----------------------------------. . (up to + FB)

Ever# element in this grid needs two indicies to pin;point it. The elements are accessed ,# giving the coordinates of the element in the grid. 2or instance to set the element ",G to the value %", one would writearrayX$YX5Y = #$;

The usual terminolog# for the two indicies is that the first gives the row num,er in the grid and that the second gives the column num,er in the grid. B/ows go along, columns hold up the ceiling.C 5n arra# cannot ,e stored in the memor# as a grid- computer memor# is a one dimensional thing. 5rra#s are therefore stored in rows. The following arra#-----------Q # Q $ Q 5 Q -----------Q 7 Q 8 Q : Q

-----------Q ; Q = Q > Q ------------

would ,e stored-----------------------------------Q # Q $ Q 5 Q 7 Q 8 Q : Q ; Q = Q > Q -----------------------------------* RG? - # * RG? - $ * RG? -5 *

5nother wa# of sa#ing that arra#s are stored row;wise is to sa# that the second index varies fastest, ,ecause a two;dimensional arra# is alwa#s thought of as...
arrayXrowYXcolumnY

so for ever# row stored, there will ,e lots of columns inside that row. That means the column index goes from !..+ FB inside ever# row, so it is changing faster as the line of storage is followed. 5 three dimensional arra#, li*e a cu,e or a cu,oid, could also ,e defined in the same *ind of wa#dou%le cu%eX+ FBYX+ FBYX+ FBY;

or with different limits on each dimensionshort notcu%icX$YX:YX=Y;

Three dimensional arra#s are stored according to the same pattern as two dimensional arra#s. The# are *ept in computer memor# as a linear se8uence of varia,le stores and the last index is alwa#s the one which varies fastest.

3rra,s and 6ested Loo$s


5rra#s of more than one dimension are usuall# handled ,# nested for loops. 5 two dimensional arra# might ,e initialiAed in the following wa#main () 0 int i(U; float arrayX+ FB#YX+ FB$Y; for (i = @; i . + FB#; iPP) 0 for (U = @; U . + FB$; UPP) 0

arrayXiYXUY = @; A A A

.n three dimensions, three nested loops would ,e neededmain () 0 int i(U(6; float arrayX+ FB#YX+ FB$YX+ FB5Y; for (i = @; i . + FB#; iPP) 0 for (U = @; U . + FB$; UPP) 0 for (6 = @; 6 . + FB5; 6PP) 0 arrayXiYXUYX6Y = @; A A A A

5n example program helps to show how this happens in practice. The example ,elow demonstrates the so;called DGame of LifeD. The aim is to mimic something li*e cell reproduction ,# appl#ing some rigid rules to a pattern of dots . and stars *. 5 dot is a place where there is no life Bas we *now it:C and a star is a place in which there is a living thing. The rules will ,e clear from the listing. Things to notice are the wa# the program traverses the arra#s and the wa# in which it chec*s that it is not overstepping the ,oundaries of the arra#s.

%*a#$le Listing
)*********************************************************) )* *) )* Rame of Eife *) )* *) )*********************************************************) )* )* )* )* )* )* )* 9ased upon an article from +cientific 1merican in #>;@. +imulates the reproduction of cells which depend on one another. 3he rules are that cells will only sur4i4e if they ha4e a certain num%er of neigh%ours to support them %ut not too many( or there won"t %e enough foodI *) *) *) *) *) *) *)

-include .stdio.h/ -define + FB -define J1CNUJ -define N9GUN<+ $@ #8 (a/=@)MM(a.+ FB)MM(%/=@)MM(%.+ FB)

-define NGRB+,GN+B

)*********************************************************) )* Ee4el @ *) )*********************************************************) main () 0 int countX+ FBYX+ FBY; char arrayX+ FBYX+ FBY; int generation = @; printf (&Rame of Eife2n2n2n&); nitialiNe1rray(array); while (NGRB+,GN+B) 0 DountNeigh%ours(array(count); 9uildNextReneration(array(count); Update<isplay(array(PPgeneration); printf (&2n2n] for Ouit. RB3URN to continue.2n&); if(Ouit()) %rea6; A A )**********************************************************) )* Ee4el # *) )**********************************************************) nitialiNe1rray (array) char arrayX+ FBYX+ FBY; 0 int i(U; char ch; printf printf printf printf (&2nBnter starting setup. 3ype "." for empty&); (&2nand any other character for occupied.2n&); (&RB3URN after each line.2n2n&); (&1rray siNe guide:2n2n&); )* Ret starting conditions *)

for (i=@; iPP . + FB; printf(&'c&("Z")); printf (&2n2n&); for (i = @; i . + FB; iPP) 0 for (U = @; U . + FB; UPP) 0 scanf (&'c&(Mch); if (ch == ".") 0 arrayXiYXUY = "."; A else 0 arrayXiYXUY = "*"; A A

s6ipgar%(); A printf (&2n2n nput is complete. ,ress RB3URN.&); s6ipgar%(); A )********************************************************) DountNeigh%ours (array(count) )* count all neigh%ours *) char arrayX+ FBYX+ FBY; int countX+ FBYX+ FBY; 0 int i(U; for (i = @; i . + FB; iPP) 0 for (U = @; U . + FB; UPP) 0 countXiYXUY = numali4e(array(i(U); A A A )*******************************************************) 9uildNextReneration (array(count) )* 1 cell will sur4i4e if it has two or three *) )* neigh%ours. New life will %e %orn to a dead *) )* cell if there are exactly three neigh%ours *) char arrayX+ FBYX+ FBY; int countX+ FBYX+ FBY; 0 int i(U; for (i = @; i . + FB; iPP) 0 for (U = @; U . + FB; UPP) 0 if (arrayXiYXUY == "*") 0 switch (countXiYXUY) 0 case $ : case 5 : continue; default: arrayXiYXUY = "."; %rea6; A A else 0 switch (countXiYXUY) 0 case 5 : arrayXiYXUY = "*"; %rea6;

default: continue; A A A A A

)*******************************************************) Update<isplay (array(g) char arrayX+ FBYX+ FBY; int g; 0 int i(U; printf (&2n2nReneration 'd2n2n&(g); for (i = @; i . + FB; iPP) 0 for (U = @; U . + FB; UPP) 0 printf(&'c&(arrayXiYXUY); A printf(&2n&); A A )*******************************************************) )* Ee4el $ *) )*******************************************************) numali4e (array(i(U) )* <on"t count arrayXi(UY : only its neigh%ours *) )* 1lso chec6 that ha4en"t reached the %oundary *) )* of the array *) char arrayX+ FBYX+ FBY; int i(U; 0 int a(%(census; census = @; for (a = (i-#); (a .= (iP#)); aPP) 0 for (% = (U-#); (% .= (UP#)); %PP) 0 if ( N9GUN<+ MM (arrayXaYX%Y == "*")) 0 censusPP; A A A if (arrayXiYXUY == "*") census--; return (census); )* print out life array *)

A )********************************************************) )* 3ool6it input *) )********************************************************) Ouit() 0 char ch; while (NGRB+,GN+B) 0 scanf (&'c&(Mch); if (ch I= "2n") s6ipgar%(); switch (ch) 0 case "O" : case "]" : return (#); default : return (@); A A A )********************************************************) s6ipgar% () 0 while (getchar() I= "2n") 0 A A

+ut$ut of 5a#e of Life


Rame of Eife Bnter starting setup. 3ype "." for empty and any other character for occupied. RB3URN after each line. 1rray + FB guide: ZZZZZZZZZZZZZZZZZZZZ (user types in: .................... .................... ..................... ..................... ..................... ..........***........ ...........*......... ...................... ..................... ..................... ..................... ********************* ..................... ( t doesn"t matter if the input spills o4er the + FB guide( %ecause &s6ipgar%()& discards it.)

...................... .................... ..................... ...................... ...................... ...................... ...................... )

nput is complete. ,ress RB3URN. Reneration # .................... .................... .................... .................... ...........*........ ..........***....... ..........***....... .................... .................... .................... .******************. .******************. .******************. .................... .................... .................... .................... .................... .................... .................... ] for Ouit. RB3URN to continue. Reneration $ .................... .................... .................... .................... ..........***....... .................... ..........*.*....... ...........*........ .................... ..****************.. .*................*. *..................* .*................*. ..****************.. .................... .................... .................... ....................

.................... .................... ] for Ouit. RB3URN to continue. Reneration 5 .................... .................... .................... ...........*........ ...........*........ ..........*.*....... ...........*........ ...........*........ ...*******...****... ..****************.. .******************. **................** .******************. ..****************.. ...**************... .................... .................... .................... .................... .................... ] for Ouit. RB3URN to continue. Reneration 7 .................... .................... .................... .................... ..........***....... ..........*.*....... ..........***....... ....*****.*.*.**.... ..*..............*.. .*................*. *..................* *..................* *..................* .*................*. ..*..............*.. ....************.... .................... .................... .................... .................... ] for Ouit. RB3URN to continue.

etc... Tr# experimenting with different starting patterns.

Initiali2ing 3rra,s
5rra#s can ,e initialiAed in two wa#s. The first wa# is ,# assigning ever# element to some value with a statement li*earrayX$Y = 7$; arrayX5Y = #$;

or perhaps with the aid of one or more for loops. +ecause it is tedious, to sa# the least, not to mention uneconomical, to initialiAe the values of each element to as different value, C provides another method, which emplo#s a single assignment operator = and curl# ,races 0 A. This $ethod only works for static !ariables and e%ternal !ariables. /ecall that arra#s are stored row;wise or with the last index var#ing fastest. 5 G ,# G arra# could ,e initialiAed in the following wa#static int arrayX5YX5Y = 0 0#@($5(7$A( 0#(:87(@A( 07@:8$($$(@A A;

The internal ,races are unnecessar#, ,ut help to distinguish the rows from the columns. The same thing could ,e writtenint arrayX5YX5Y = 0 #@($5(7$( #(:87(@ 7@:8$($$(@ A;

Ta*e care to include the semicolon at the end of the curl# ,race which closes the assignment. Note that, if there are not enough elements in the curl# ,races to account for ever# single element in an arra#, the remaining elements will ,e filled out with Aeros. 4tatic varia,les are alwa#s guaranteed to ,e initialiAed to Aero an#wa#, whereas auto or local varia,les are guaranteed to ,e gar,age- this is ,ecause static storage is created ,# the compiler in the ,od# of a program, whereas auto or local storage is created at run time.

3rra,s and Pointers


The information a,out how arra#s are stored was not included ?ust for interest. There is another wa# of loo*ing at arra#s which follows the +CPL idea of an arra# as simpl# a ,loc* of memor#. 5n arra# can ,e accessed with pointers as well as with XY s8uare ,rac*ets. The na$e of an array !ariable standing alone is actually a pointer to the first ele$ent in the array. 2or example- if an arra# is declared
float num%ersX57Y;

then num%ers is a pointer to the first floating point num,er in the arra#@ num%ers is a pointer in its own right. B.n this case it is t#pe Ipointer to float9.C 4o the first element of the arra# could ,e accessed ,# writingnum%ersX@Y = $$.5;

or ,# writing
*num%ers = $$.5;

2or character arra#s, which are dealt with in some depth in chapter "!, this gives an alternative wa# of getting at the elements in the arra#.
char arraynameX8Y; char *ptr; for (ptr = arrayname; ptr .= arraynameP7; ptrPP) 0 *ptr = @; A

The code a,ove sets the arra# arrayname to Aero. This method of getting at arra# data is not recommended ,# this author except in ver# simple computer environments. .f a program is running on a normal microcomputer, then there should ,e few pro,lems with this alternative method of handling arra#s. 1n the hand, if the microcomputer is multi; tas*ing, or the program is running on a larger s#stem which has a limited manager, then memor# ceases to ,e something which can ,e thought of as a se8uence of ,oxes standing next to one another. 5 multi;tas*ing s#stem shares memor# with other programs and it ta*es what it can find, where it can find it. The upshot of this is that it is not possi,le to guarantee that arra#s will ,e stored in one simple string of memor# locations- it might ,e scattered around in different places. 4o
ptr = arrayname P 8;

might not ,e a pointer to the fifth character in a character arra#. This could ,e found instead using the M operator. 5 pointer to the fifth element can ,e relia,l# found withptr = M(arraynameX8Y);

+e warned:

3rra,s as Para#eters
<hat happens if we want to pass an arra# as a parameterF 6oes the program cop# the entire arra# into local storageF The answer is no ,ecause it would ,e a waste of time and memor#. 5rra#s can ,e passed as parameters, ,ut onl# as varia,le ones. This is a simple matter, ,ecause the name of the arra# is a pointer to the arra#. The Game of Life program a,ove does this. Notice from that program how the declarations for the parameters are made.
main () 0 char arrayX$5Y; function (array); ..... A function (arrayformal) char arrayformalX$5Y; 0 A

5n# function which writes to the arra#, passed as a parameter, will affect the original cop#. 5rra# parameters are alwa#s varia,le parameters

(uestions
%. Given an# arra#, how would #ou find a pointer to the start of itF ". 7ow do #ou pass an arra# as a parameterF <hen the parameter is received ,# a function does C allocate space for a local varia,le and cop# the whole arra# to the new locationF G. <rite a statement which declares an arra# of t#pe dou,le which measures ,# H. <hat num,ers can ,e written in the indicies of the arra#F

/trings
*o$$unication with arrays.

4trings are pieces of text which can ,e treated as values for varia,les. .n C a string is represented as some characters enclosed ,# dou,le 8uotes.
&3his is a string&

5 string ma# contain an# character, including special control characters, such as 2n, 2r, 2; etc...
&9eepI 2; Newline 2n...&

Conventions and 6eclarations4trings 5rra#s and Pointers5rra#s of 4tringsExample "%4trings from the user7andling stringsExample ""4tring .nputE1utputExample "G>uestions "!-

!onventions and 'eclarations


There is an important distinction ,etween a string and a single character in C. The convention is that single characters are enclosed ,# single 8uotes e.g. * and have the t#pe char. 4trings, on the hand, are enclosed ,# dou,le 8uotes e.g. &string...& and have the t#pe Dpointer to charD (char *) or arra# of char. 7ere are some declarations for strings which are given without immediate explanations.
)**********************************************************) )* *) )* +tring <eclaration *) )* *) )**********************************************************) -define + FB #@

char *glo%alKstring#; char glo%alKstring$X+ FBY; main () 0 char *autoKstring; char arraystrX+ FBY; static char *statKstrng; static char statarraystrX+ FBY; A

/trings, 3rra,s and Pointers


5 string is reall# an arra# of characters. .t is stored at some place the memor# and is given an end mar*er which standard li,rar# functions can recogniAe as ,eing the end of the string. The end mar*er is called the Aero Bor NUEEC ,#te ,ecause it is ?ust a ,#te which contains the value Aero- 2@. Programs rarel# gets to see this end mar*er as most functions which handle strings use it or add it automaticall#. 4trings can ,e declared in two main wa#s@ one of these is as an arra# of characters, the other is as a pointer to some pre;assigned arra#. Perhaps the simplest wa# of seeing how C stores arra#s is to give an extreme example which would pro,a,l# never ,e used in practice. Thin* of how a string called string might ,e used to to store the message DTedious:D. The fact that a string is an arra# of characters might lead #ou to write something li*e-define EBNR3H >; main () 0 char stringXEBNR3HY; stringX@Y stringX#Y stringX$Y stringX5Y stringX7Y stringX8Y stringX:Y stringX;Y stringX=Y = = = = = = = = = "3"; "e"; "d"; "i"; "o"; "u"; "s"; "I"; "2@";

printf (&'s&( string); A

This method of handling strings is perfectl# accepta,le, if there is time to waste, ,ut it is so la,orious that C provides a special initialiAation service for strings, which ,#passes the need to assign ever# single character with a new assignment:. There are six wa#s of assigning constant strings to arra#s. B5 constant string is one which is actuall# t#ped into the program, not one which in t#ped in ,# the user.C The# are written into a short compila,le program ,elow. The explanation follows.
)**********************************************************) )* *) )* +tring nitialiNation *) )* *) )**********************************************************) char *glo%alKstring# = &1 string declared as a pointer&; char glo%alKstring$XY = &<eclared as an array&;

main () 0 char *autoKstring = &initialiNer...&; static char *statKstrng = &initialiNer...&; static char statarraystrXY = &initialiNer....&; )* char arraystrXY = &initialiNer....&; + EEBR1EI *) )* 3his is %ecause the array is an &auto& type *) )* which cannot %e preinitialiNed( %ut... *) char arraystrX$@Y; printf (&'s 's&( glo%alKstring#( glo%alKstring$); printf (&'s 's 's&( autoKstring( statKstrng( statarraystr); A )* end *)

The details of what goes on with strings can ,e difficult to get to grips with. .t is a good idea to get revise pointers and arra#s ,efore reading the explanations ,elow. Notice the diagrams too- the# are pro,a,l# more helpful than words. The first of these assignments is a glo,al, static varia,le. )ore correctl#, it is a pointer to a glo,al, static arra#. 4tatic varia,les are assigned storage space in the ,od# of a program when the compiler creates the executa,le code. This means that the# are saved on dis* along with the program code, so the# can ,e initialiAed at compile time. That is the reason for the rule which sa#s that onl# static arra#s can ,e initialiAed with a constant expression in a declaration. The first statement allocates space for a pointer to an arra#. Notice that, ,ecause the string which is to ,e assigned to it, is t#ped into the program, the compiler can also allocate space for that in the executa,le file too. .n fact the compiler stores the string, adds a Aero ,#te to the end of it and assigns a pointer to its first character to the varia,le called glo%alKstring#. The second statement wor*s almost identicall#, with the exception that, this time the compiler sees the declaration of a static arra#, which is to ,e initialiAed. Notice that there is no siAe declaration in the s8uare ,rac*ets. This is 8uite legal in fact- the compiler counts the num,er of characters in the initialiAation string and allocates ?ust the right amount of space, filling the string into that space, along with its end mar*er as it goes. /emem,er also that the name of the arra# is a pointer to the first character, so, in fact, the two methods are identical. The third expression is the same *ind of thing, onl# this time, the declaration is inside the function main() so the t#pe is not static ,ut auto. The difference ,etween this and the other two declarations is that this pointer varia,le is created ever# time the function main() is called. .t is new each time and the same thing holds for an# other function which it might have ,een defined in- when the function is called, the pointer is created and when it ends, it is destro#ed. The string which initialiAes it is stored in the executa,le file of the program B,ecause it is t#ped into the textC. The compiler returns a value which

is a pointer to the string9s first character and uses that as a value to initialiAe the pointer with. This is a slightl# round a,out wa# of defining the string constant. The normal thing to do would ,e to declare the string pointer as ,eing static, ,ut this is ?ust a matter of st#le. .n fact this is what is done in the fourth example. The fifth example is again identical, in practice to other static t#pes, ,ut is written as an Iopen9 arra# with an unspecified siAe. The sixth example is for,idden: The reason for this might seem rather trivial, ,ut it is made in the interests of efficienc#. The arra# declared is of t#pe auto- this means that the whole arra# is created when the function is called and destro#ed afterwards. auto;arra#s cannot ,e initialiAed with a string ,ecause the# would have to ,e re;initialiAed ever# time the arra# were created- that is, each time the function were called. The final example could ,e used to overcome this, if the programmer were inclined to do so. 7ere an auto arra# of characters is declared Bwith a siAe this time, ,ecause there is nothing for the compiler to count the siAe ofC. There is no single assignment which will fill this arra# with a string though- the programmer would have to do it character ,# character so that the inefficienc# is made as plain as possi,le:

3rra,s of /trings
.n the previous chapter we progressed from one dimensional arra#s to two dimensional arra#s, or arra#s of arra#s: The same thing wor*s well for strings which are declared static. Programs can ta*e advantage of C9s eas# assignment facilities to let the compiler count the siAe of the string arra#s and define arra#s of messages. 2or example here is a program which prints out a menu for an application program)*********************************************************) )* *) )* JBNU : program which prints out a menu *) )* *) )*********************************************************) main () 0 int strKnum%er; for (strKnum%er = @; strKnum%er . #5; strKnum%erPP) 0 printf (&'s&(menutext(strKnum%er)); A A )*********************************************************) char *menutext(n) int n; 0 static char *tXY = 0 )* return n-th string ptr *)

& -------------------------------------- 2n&( & Q PP JBNU PP Q2n&( & Q [[[[[[[[[[[[ Q2n&( & Q (#) Bdit <efaults Q2n&( & Q ($) ,rint Dharge +heet Q2n&( & Q (5) ,rint Eog +heet Q2n&( & Q (7) 9ill Dalculator Q2n&( & Q (O) ]uit Q2n&( & Q Q2n&( & Q Q2n&( & Q ,lease Bnter Dhoice Q2n&( & Q Q2n&( & -------------------------------------- 2n& A; return (tXnY); A

Notice the wa# in which the static declaration wor*s. .t is initialiAed once at compile time, so there is effectivel# onl# one statement in this function and that is the return statement. This function retains the pointer information from call to call. The )orse coder program could ,e rewritten more economicall# using static strings, 4ee Example %H.

%*a#$le Listing
)************************************************) )* *) )* static string array *) )* *) )************************************************) )* Jorse code program. Bnter a num%er and *) )* find out what it is in Jorse code *) -include .stdio.h/ -define DG<B @ )*************************************************) main () 0 short digit; printf (&Bnter any digit in the range @..>&); scanf (&'h&(Mdigit); if ((digit . @) QQ (digit / >)) 0 printf (&Num%er was not in range @..>&); return (DG<B); A printf (&3he Jorse code of that digit is &);

Jorse (digit); A )************************************************) Jorse (digit) short digit; 0 static char *codeXY = 0 &dummy&( &-----&( &.----&( &..---&( &...--&( &....-&( &.....&( &-....&( &--...&( &---..&( &----.&( A; )* index starts at @ *) )* print out Jorse code *)

printf (&'s2n&(codeXdigitY); A

/trings fro# the user


5ll the strings mentioned so far have ,een t#ped into a program ,# the programmer and stored in a program file, so it has not ,een necessar# to worr# a,out where the# were stored. 1ften though we would li*e to fetch a string from the user and store it somewhere in the memor# for later use. .t might even ,e necessar# to get a whole ,unch of strings and store them all. +ut how will the program *now in advance how much arra# space to allocate to these stringsF The answer is that it won9t, ,ut that it doesn9t matter at all: 1ne wa# of getting a simple, single string from the user is to define an arra# and to read the characters one ,# one. 5n example of this was the Game of Life program the the previous chapter

6efine the arra# to ,e a certain siAe Chec* that the user does not t#pe in too man# characters. Use the string in that arra#.

5nother wa# is to define a static string with an initialiAer as in the following example. The function filename() as*s the user to t#pe in a filename, for loading or saving ,# and return it to a calling function.
char *filename() 0 static char *filenm = &........................&;

do

0 printf (&Bnter filename :&); scanf (&'$7s&(filenm); s6ipgar%(); A while (strlen(filenm) == @); return (filenm); A

The string is made static and given an initialiAing expression and this forces the compiler to ma*e some space for the string. .t ma*es exactl# " characters plus a Aero ,#te in the program file, which can ,e used ,# an application. Notice that the conversion string in scanf prevents the characters from spilling over the ,ounds of the string. The function strlen() is a standard li,rar# function which is descri,ed ,elow@ it returns the length of a string. s6ipgar%() is the function which was introduced in chapter %H. Neither of the methods a,ove is an# good if a program is going to ,e fetching a lot of strings from a user. .t ?ust isn9t practical to define lots of static strings and expect the user to t#pe into the right siAe ,oxes: The next step in string handling is therefore to allocate memor# for strings personall#- in other words to ,e a,le to sa# how much storage is needed for a string while a program is running. C has special memor# allocation functions which can do this, not onl# for strings ,ut for an# *ind of o,?ect. 4uppose then that a program is going to get ten strings from the user. 7ere is one wa# in which it could ,e done%. 6efine one large, static string Bor arra#C for getting one string at a time. Call this a string ,uffer, or waiting place. ". 6efine an arra# of ten pointers to characters, so that the strings can ,e recalled easil#. G. 2ind out how long the string in the string ,uffer is. . 5llocate memor# for the string. H. Cop# the string from the ,uffer to the new storage and place a pointer to it in the arra# of pointers for reference. M. /elease the memor# when it is finished with. The function which allocates memor# in C is called malloc() and it wor*s li*e this malloc()

should ,e declared as returning the t#pe pointer to character, with the

statementchar *malloc();

ta*es one argument which should ,e an unsigned integer value telling the function how man# ,#tes of storage to allocate. .t returns a pointer to the first memor# location in that storagemalloc() char *ptr; unsigned int siNe; ptr = malloc(siNe);

The pointer returned has the value NUEE if there was no memor# left to allocate. This should alwa#s ,e chec*ed.

The fact that malloc() alwa#s returns a pointer to a character does not stop it from ,eing used for other t#pes of data too. The cast operator can force malloc() to give a pointer to an# data t#pe. This method is used for ,uilding data structures in C with DstructD t#pes. has a complementar# function which does precisel# the opposite- de;allocates memor#. This function is called free(). free() returns an integer code, so it does not have to ,e declared as ,eing an# special t#pe.
malloc()

ta*es one argument- a pointer to a ,loc* of memor# which has previousl# ,een allocated ,# malloc().
free() int returncode; returncode = free (ptr);

The pointer should ,e declaredchar *ptr;

The return code is Aero if the release was successful.

5n example of how strings can ,e created using malloc() and free() is given ,elow. 2irst of all, some explanation of 4tandard Li,rar# 2unctions is useful to simplif# the program.

Handling strings
The C 4tandard Li,rar# commonl# provides a num,er of ver# useful functions which handle strings. 7ere is a short list of some common ones which are immediatel# relevant Bmore are listed in the following chapterC. Chances are, a good compiler will support a lot more than those listed ,elow, ,ut, again, it reall# depends upon the compiler.
strlen()

This function returns a t#pe int value, which gives the length or num,er of characters in a string, not including the NUEE ,#te end mar*er. 5n example isint len; char *string; len = strlen (string);

strcpy()

This function copies a string from one place to another. Use this function in preference to custom routines- it is set up to handle an# peculiarities in the wa# data are stored. 5n example is
char *to(*from; to = strcpy (to(from);

<here to is a pointer to the place to which the string is to ,e copied and from is the place where the string is to ,e copied from.
strcmp()

This function compares two strings and returns a value which indicates how the# compared. 5n exampleint 4alue; char *s#(*s$;

4alue = strcmp(s#(s$);

The value returned is ! if the two strings were identical. .f the strings were not the same, this function indicates the B54C..C alpha,etical order of the two. s# / s$, alpha,eticall#, then the value is / @. .f s# . s$ then the value is . @. Note that num,ers come ,efore letters in the 54C.. code se8uence and also that upper case comes ,efore lower case.
strstr()

Tests whether a su,string is present in a larger string


int n; char *s#(*s$;

if (n = strstr(s#(s$)) 0 printf(&s$ is a su%string of s#( starting at 'd&(n); A

strncpy()

This function is li*e strcpy, ,ut limits the cop# to no more than n characters.
strncmp()

This function is li*e strcmp, ,ut limits the comparison to no more than n characters. )ore string functions are descri,ed in the next section along with a host of 4tandard Li,rar# 2unctions.

%*a#$le Listing
This program aims to get ten strings from the user. The strings ma# not contain an# spaces or white space characters. .t wor*s as followsThe user is prompted for a string which heEshe t#pes into a ,uffer. The length of the string is tested with strlen() and a ,loc* of memor# is allocated for it using malloc(). BNotice that this ,loc* of memor# is one ,#te longer than the value returned ,# strlen(), ,ecause strlen() does not count the end of string mar*er 2@.C malloc() returns a pointer to the space allocated, which is then stored in the arra# called array. 2inall# the strings is copied from the ,uffer to the new storage with the li,rar# function strcpy(). This process is repeated for each of the %! strings. Notice that the program exits through a low level function called ]uit+afely(). The reason for doing this is to exit from the program neatl#, while at the same time remem,ering to perform all a programmer9s duties, such as de;allocating the memor# which is no longer needed.

]uit+afely() uses the function exit() which should ,e function. exit() allows a program to end at an# point.

provided as a standard li,rar#

)******************************************************) )* *) )* +tring storage allocation *) )* *) )******************************************************) -include .stdio.h/ )* -include another file for malloc() and *) )* strlen() VVV. Dhec6 the compiler manualI *) -define NGGL+3R -define 9UL+ FB -define DG<B #@ $88 @

)******************************************************) )* Ee4el @ *) )******************************************************) main () 0 char *arrayXNGGL+3RY( *malloc(); char %ufferX9UL+ FBY; int i; for (i = @; i . NGGL+3R; iPP) 0 printf (&Bnter string 'd :&(i); scanf (&'$88s&(%uffer); arrayXiY = malloc(strlen(%uffer)P#); if (arrayXiY == NUEE) 0 printf (&Dan"t allocate memory2n&); ]uit+afely (array); A strcpy (arrayXiY(%uffer); A for (i = @; i . NGGL+3R; iPP) 0 printf (&'s2n&(arrayXiY); A ]uit+afely(array); A )******************************************************) )* +na6es M EaddersI *) )******************************************************) ]uit+afely (array) )* ]uit M de-alloc memory *)

char *arrayXNGGL+3RY; 0 int i( len; for (i = @; i . NGGL+3R; iPP) 0 len = strlen(arrayXiY) P #; if (free (arrayXiY) I= @) 0 printf (&<e%ug: free failed2n&); A A exit (DG<B); A )* end *)

/tring In$ut:+ut$ut
+ecause strings are recogniAed to ,e special o,?ects in C, some special li,rar# functions for reading and writing are provided for them. These ma*e it easier to deal with strings, without the need for special user;routines. There are four of these functionsgets() puts() sprintf() sscanf()

gets()

getsBCputsBCsprintfBCsscanfBC-

This function fetches a string from the standard input file stdin and places it into some ,uffer which the programmer must provide.
-define + FB $88

char *sptr( %ufferX+ FBY; strptr = gets(%uffer);

.f the routine is successful in getting a string, it returns the value %uffer to the string pointer strptr. 1therwise it returns NUEE BQQ!C. The advantage of gets() over scanf(&'s&..) is that it will read spaces in strings, whereas scanf() usuall# will not. gets() 8uits reading when it finds a newline character- that is, when the user presses RB3URN.

N1TE- there are valid concerns a,out using this function. 1ften it is implemented as a macro with poor ,ounds chec*ing and can ,e exploited to produce memor# corruption ,# s#stem attac*ers. .n order to write more secure code, use fgets() instead.

puts() puts() sends a string to the output file stdout, until it finds a NUEE end of string The NUEE ,#te is not written to stdout, instead a newline character is written. char *string; int returncode; returncode = puts(string);

mar*er.

puts() returns an integer value, whose value is onl# guaranteed if there is an returncode == BGL if an end of file was encountered or there was an error. sprintf()

error.

This is an interesting function which wor*s in almost the same wa# as printf(), the exception ,eing that it prints to a string: .n other words it treats a string as though it were an output file. This is useful for creating formatted strings in the memor#. 1n most s#stems it wor*s in the following wa#int n; char *sp; n = sprintf (sp( &control string&( parameters( 4alues);

is an integer which is the num,er of characters printed. sp is a pointer to the destination string or the string which is to ,e written to. Note carefull# that this function does not perform an# chec* on the output string to ma*e sure that it is long enough to contain the formatted output. .f the string is not large enough, then a crash could ,e in store: This can also ,e considered a potential securit# pro,lem, since ,uffer overflows can ,e used to capture control of important programs. Note that on s#stem 3 Unix s#stems the sprintf functionr returns a pointer to the start of the printed string, ,rea*ing the pattern of the other printf functions. To ma*e such an implementation compati,le with the usual form #ou would have to writen n = strlen(sprintf(parameters&&&&&&)); sscanf()

This function is the complement of sprintf(). .t reads its input from a string, as though it were an input file.
int n;

char *sp; n = sscanf (sp(&control string&( pointers...);

is a pointer to the string which is to ,e read from. The string must ,e NUEE terminated Bit must have a Aero;,#te end mar*er 9P!9C. sscanf() returns an integer value which holds the num,er of items successfull# matched or BGL if an end of file mar*er was read or an error occurred. The conversion specifiers are identical to those for scanf().
sp

%*a#$le Listing
)************************************************) )* *) )* Lormatted strings *) )* *) )************************************************) )* program rewrites s# in re4erse into s$ *) -include .stdio.h/ -define + FB -define DG<B $@ @

)************************************************) main () 0 static char *s# = &string $.5 88x&; static char *s$ = &....................&; char ch( *stringX+ FBY; int i(n; float x; sscanf (s#(&'s 'f 'd 'c&( string( Mx( Mi( Mch); n = sprintf (s$(&'c 'd 'f 's&( ch( i( x( string); if (n / + FB) 0 printf (&Brror: string o4erflowedI2n&); exit (DG<B); A puts (s$); A

(uestions
%. <hat are the two main wa#s of declaring strings in a programF ". 7ow would #ou declare a static arra# of stringsF

G. <rite a program which gets a num,er ,etween ! and & and prints out a different message for each num,er. Use a pre;initialiAed arra# to store the strings.

Putting together a $rogra#


Putting it all together.

argc and argvgetoptenvp-

"he argu#ent vector


C was written in order to implement Unix in a porta,le form. Unix was designed with a command language which was ,uilt up of independent programs. These could ,e passed arguments on the command line. 2or instancels -l )etc cc -o program prog.c

.n these examples, the first word is the command itself, while the su,se8uent words are options and arguments to the command. <e need some wa# getting this information into a C program. Unix solved this pro,lem ,# passing C programs an arra# of these arguments together with their num,er as parameters to the function main(). 4ince then most other operating s#stems have adopted the same model, since it has ,ecome a part of the C language.
main (argc(arg4) int argc; char *arg4XY; 0 A

The traditional names for the parameters are the argument count argc and the argument vector Barra#C arg4. The operating s#stem call which starts the C program ,rea*s up the command line into an arra#, where the first element arg4X@Y is the name of the command itself and the last argument arg4Xargc-#Y is the last argument. 2or example, in the case of
cc -o program prog.c

would result in the values

arg4X@Y arg4X#Y arg4X$Y arg4X5Y

cc ;o program

prog.c The following program prints out the command line argumentsmain (argc(arg4) int argc; char *arg4XY; 0 int i; printf (&3his program is called 's2n&(arg4X@Y); if (argc / #) 0 for (i = #; i . argc; iPP) 0 printf(&arg4X'dY = 's2n&(i(arg4XiY); A A else 0 printf(&Dommand has no arguments2n&); A A

Processing o$tions
getopt

%nviron#ent varia les


<hen we write a C program which reads command line arguments, the# are fed to us ,# the argument vector. Unix processes also a set of text varia,le associations called environment varia,les. Each child process inherits the environment of its parent. The static environment varia,les are stored in a special arra# which is also passed to main() and can ,e read if desired.
main (argc(arg4(en4p) int argc; char *arg4XY( *en4pXY; 0 A

The arra# of strings en4pXY is a list of values of the en!iron$ent !ariables of the s#stem, formatted ,#
N1JB=4alue

This gives C programmers access to the shell9s glo,al environment. .n addition to the en4p vector, it is possi,le to access the environment varia,les through the call geten4(). This is used as follows@ suppose we want to access the shell environment varia,le THGJB.
char *string; string = geten4(&HGJB&);

is now a pointer to static ,ut pu,lic data. =ou should not use string as if it were #ou9re own propert# ,ecause it will ,e used again ,# the s#stem. Cop# it9s contents to another string ,efore using the data.
string char %ufferX8@@Y; strcpy (%uffer(string);

/$ecial Li rar, -unctions and Macros


*hecking character types. -andling strings. Doing $aths. C provides a repertoire of standard li,rar# functions and macros for specialiAed purposes Band for the advanced userC. These ma# ,e divided into various categories. 2or instance

Character identification Bctype.hC 4tring manipulation Bstring.hC )athematical functions Bmath.hC

5 program generall# has to -include special header files in order to use special functions in li,raries. The names of the appropriate files can ,e found in particular compiler manuals. .n the examples a,ove the names of the header files are given in parentheses.

Character .dentificationExample " 1utput " 4tring )anipulationExample "H)athematical 2unctionsExamples "M)aths ErrorsExample "(-

>uestions "%-

!haracter Identification
4ome or all of the following functionsEmacros will ,e availa,le for identif#ing and classif#ing single characters. The programmer ought to ,eware that it would ,e natural for man# of these facilities to exist as macros rather than functions, so the usual remar*s a,out macro parameters appl#, 4ee Preprocessor. 5n example of their use is given a,ove. 5ssume that Itrue9 has an# non;Aero, integer value and that Ifalse9 has the integer value Aero. ch stands for some character, or char t#pe varia,le.
isalpha(ch)

This returns true if ch is alpha,etic and false otherwise. 5lpha,etic means a..N or 1..F.
isupper(ch)

islower(ch)

/eturns true if the character was upper case. .f ch was not an alpha,etic character, this returns false. /eturns true if the character was lower case. .f ch was not an alpha,etic character, this returns false.

isdigit(ch) isxdigit(ch)

/eturns true if the character was a digit in the range !..&. /eturns true if the character was a valid hexadecimal digit- that is, a num,er from !..& or a letter a..f or 5..2.

isspace(ch)

ispunct(ch) isalnum(ch) isprint(ch)

/eturns true if the character was a white space character, that is- a space, a 319 character or a newline. /eturns true if ch is a punctuation character. /eturns true if a character is alphanumeric- that is, alpha,etic or digit. /eturns true if the character is printa,le- that is, the character is not a control character.

isgraph(ch)

iscntrl(ch)

/eturns true if the character is graphic. i.e. if the character is printa,le Bexcluding the spaceC /eturns true if the character is a control character. i.e. 54C.. values ! to G% and %"(.

isascii(ch)

iscsym(ch)

/eturns true if the character is a valid 54C.. character- that is, it has a code in the range !..%"(. /eturns true if the character was a character which could ,e used in a C identifier.

toupper(ch)

This converts the character ch into its upper case counterpart. This does not affect characters which are alread# upper case, or characters which do not have a particular case, such as digits.

tolower(ch)

toascii(ch)

This converts a character into its lower case counterpart. .t does not affect characters which are alread# lower case. This strips off ,it ( of a character so that it is in the range !..%"(- that is, a valid 54C.. character.

%*a#$les
)********************************************************) )* *) )* <emonstration of character utility functions *) )* *) )********************************************************) )* prints out all the 1+D characters which gi4e *) )* the 4alue &true& for the listed character fns *) -include .stdio.h/ -include .ctype.h/ -define 1EEDH1R+ )* contains character utilities *) ch = @; isascii(ch); chPP

)********************************************************) main () 0 char ch; printf (&S1E < DH1R1D3BR+ LRGJ isalpha()2n2n&); for (1EEDH1R+) 0 if (isalpha(ch)) 0 printf (&'c &(ch); A A printf (&2n2nS1E < DH1R1D3BR+ LRGJ isupper()2n2n&); for (1EEDH1R+) 0 if (isupper(ch)) 0 printf (&'c &(ch); A A printf (&2n2nS1E < DH1R1D3BR+ LRGJ islower()2n2n&); for (1EEDH1R+) 0 if (islower(ch)) )* 1 criminally long main programI *)

0 printf (&'c &(ch); A

printf (&2n2nS1E < DH1R1D3BR+ LRGJ isdigit()2n2n&); for (1EEDH1R+) 0 if (isdigit(ch)) 0 printf (&'c &(ch); A A printf (&2n2nS1E < DH1R1D3BR+ LRGJ isxdigit()2n2n&); for (1EEDH1R+) 0 if (isxdigit(ch)) 0 printf (&'c &(ch); A A printf (&2n2nS1E < DH1R1D3BR+ LRGJ ispunct()2n2n&); for (1EEDH1R+) 0 if (ispunct(ch)) 0 printf (&'c &(ch); A A printf (&2n2nS1E < DH1R1D3BR+ LRGJ isalnum()2n2n&); for (1EEDH1R+) 0 if (isalnum(ch)) 0 printf (&'c &(ch); A A printf (&2n2nS1E < DH1R1D3BR+ LRGJ iscsym()2n2n&); for (1EEDH1R+) 0 if (iscsym(ch)) 0 printf (&'c &(ch); A A A

Progra# +ut$ut

S1E < DH1R1D3BR+ LRGJ isalpha() 1 9 D < B L R H ^ W E J N G , ] R + 3 U S ? C \ F a % c d e f g h i U 6 l m n o p O r s t u 4 w x y N S1E < DH1R1D3BR+ LRGJ isupper() 1 9 D < B L R H ^ W E J N G , ] R + 3 U S ? C \ F

S1E < DH1R1D3BR+ LRGJ islower() a % c d e f g h i U 6 l m n o p O r s t u 4 w x y N S1E < DH1R1D3BR+ LRGJ isdigit() @ # $ 5 7 8 : ; = > S1E < DH1R1D3BR+ LRGJ isxdigit() @ # $ 5 7 8 : ; = > 1 9 D < B L a % c d e f S1E < DH1R1D3BR+ LRGJ ispunct() I & - T ' M " ( ) * P ( - . ) : ; . = / V _ X 2 Y Z K ! 0 Q A [ S1E < DH1R1D3BR+ LRGJ isalnum() @ # $ 5 7 8 : ; = > 1 9 D < B L R H ^ W E J N G , ] R + 3 U S ? C \ F a % c d e f g h i U 6 l m n o p O r s t u 4 w x y N S1E < DH1R1D3BR+ LRGJ iscsym() @ # $ 5 7 8 : ; = > 1 9 D < B L R H ^ W E J N G , ] R + 3 U S ? C \ F K a % c d e f g h i U 6 l m n o p O r s t u 4 w x y N

/tring Mani$ulation
The following functions perform useful functions for string handling, 4ee 4trings.
strcat()

This function DconcatenatesD two strings- that is, it ?oins them together into one string. The effect ofchar *new(*this( ontoX$88Y; new = strcat(onto(this);

is to ?oin the string this onto the string onto. new is a pointer to the complete string@ it is identical to onto. )emor# is assumed to have ,een allocated for the starting strings. The string which is to ,e copied to must ,e large enough to accept the new string, tagged onto the end. .f it is not then unpredicta,le effects will result. B.n some programs the user might get awa# without declaring enough space for the DontoD string, ,ut in general the results will ,e gar,age, or even a crashed machine.C To ?oin two static strings together, the following code is re8uired-

char *s# = &string one&; char *s$ = &string two&; main () 0 char %ufferX$88Y; strcat(%uffer(s#); strcat(%uffer(s$); A

,uffer would then contain Dstring onestring twoD.


strlen()

This function returns a t#pe int value, which gives the length or num,er of characters in a string, not including the NUEE ,#te end mar*er. 5n example isint len; char *string; len = strlen (string);

strcpy()

This function copies a string from one place to another. Use this function in preference to custom routines- it is set up to handle an# peculiarities in the wa# data are stored. 5n example is
char *to(*from; to = strcpy (to(from);

<here to is a pointer to the place to which the string is to ,e copied and from is the place where the string is to ,e copied from.
strcmp()

This function compares two strings and returns a value which indicates how the# compared. 5n exampleint 4alue; char *s#(*s$;

4alue = strcmp(s#(s$);

The value returned is ! if the two strings were identical. .f the strings were not the same, this function indicates the B54C..C alpha,etical order of the two. s# / s$, alpha,eticall#, then the value is / @. .f s# . s$ then the value is . @. Note that num,ers come ,efore letters in the 54C.. code se8uence and also that upper case comes ,efore lower case. There are also variations on the theme of the functions a,ove which ,egin with strn instead of str. These ena,le the programmer to perform the same actions with the first n characters of a stringstrncat()

This function concatenates two strings ,# cop#ing the first n characters of this to the end of the onto string.
char *onto(*new(*this; new = strncat(onto(this(n);

strncpy()

This function copies the first n characters of a string from one place to another
char *to(*from; int n;

to = strncpy (to(from(n);

strncmp()

This function compares the first n characters of two strings


int 4alue; char *s#(*s$;

4alue = strcmp(s#(s$(n);

The following functions perform conversions ,etween strings and floating pointEinteger t#pes, without needing to use sscanf(). The# ta*e a pre;initialiAed string and wor* out the value represented ,# that string.
atof()

54C.. to floating point conversion.


dou%le x; char *stringptr;

x = atof(stringptr);

atoi()

54C.. to integer conversion.


int i; char *stringptr;

i = atoi(stringptr);

atol()

54C.. to long integer conversion.


long i; char *stringptr;

i = atol(stringptr);

%*a#$les
)********************************************************)

)* *) )* +tring comparison *) )* *) )********************************************************) -include .stdio.h/ -define 3RUB # -define J1CEBN 5@ )********************************************************) main () 0 char string#XJ1CEBNY(string$XJ1CEBNY; int result; while (3RUB) 0 printf (&3ype in string #:2n2n&); scanf (&'5@s&(string#); printf (&3ype in string $:2n2n&); scanf (&'5@s&(string$); result = strcmp (string#(string$); if (result == @) 0 printf (&3hose strings were the sameI2n&); A if (result / @) 0 printf (&string# / string$2n&); A if (result . @) 0 printf (&string# . string $2n&); A A A

Mathe#atical -unctions
C has a li,rar# of standard mathematical functions which can ,e accessed ,# -including the appropriate header files Bmath.h etc.C. .t should ,e noted that all of these functions wor* with dou%le or long float t#pe varia,les. 5ll of C9s mathematical capa,ilities are written for long varia,le t#pes. 7ere is a list of the functions which can ,e expected in the standard li,rar# file. The varia,les used are all to ,e declared long
int i; dou%le x(y(result; )* long int *) )* long float *)

The functions themselves must ,e declared long float or dou,le Bwhich might ,e done automaticall# in the mathematics li,rar# file, or in a separate fileC and an# constants must ,e written in floating point form- for instance, write ;.@ instead of ?ust ;.
19+()

fa%s()

)5C/1. /eturns the unsigned value of the value in parentheses. 4ee fa%s() for a function version. 2ind the a,solute or unsigned value of the value in parenthesesresult = fa%s(x);

ceil()

2ind out what the ceiling integer is- that is, the integer which is ?ust a,ove the value in parentheses. This is li*e rounding up.
i = ceil(x); )* ceil ($.$) is 5 *)

floor()

2ind out what the floor integer is- that is, the integer which is ?ust ,elow the floating point value in parentheses
i = floor(x); )* floor($.$) is $ *)

exp()

2ind the exponential value.


result = exp(x); result = exp($.;);

log()

2ind the natural BNaperianC logarithm. The value used in the parentheses must ,e unsigned- that is, it must ,e greater than Aero. .t does not have to ,e declared specificall# as unsigned. e.g.
result = log(x); result = log($.;#=$=);

log#@()

2ind the ,ase %! logarithm. The value used in the parentheses must ,e unsignedthat is, it must ,e greater than Aero. .t does not have to ,e declared specificall# as unsigned.
result = log#@(x); result = log#@(#@@@@);

pow()

/aise a num,er to the power.


result = pow(x(y); )*raise x to the power y *) result = pow(x($); )*find x-sOuared *)

result = pow($.@(5.$); )* find $ to the power 5.$ ...*) sOrt()

2ind the s8uare root of a num,er.


result = sOrt(x); result = sOrt($.@);

sin()

2ind the sine of the angle in radians.


cos() result = sin(x); result = sin(5.#7);

2ind the cosine of the angle in radians.


result = cos(x); result = cos(5.#7);

tan()

2ind the tangent of the angle in radians.


result = tan(x); result = tan(5.#7);

asin()

2ind the arcsine or inverse sine of the value which must lie ,etween R%.! and ;%.!.
result = asin(x); result = asin(#.@);

acos()

2ind the arccosine or inverse cosine of the value which must lie ,etween R%.! and ;%.!.
result = acos(x); result = acos(#.@);

atan()

2ind the arctangent or inverse tangent of the value.


result = atan(x); result = atan($@@.@);

atan$()

This is a special inverse tangent function for calculating the inverse tangent of x divided ,# #. This function is set up to find this result more accuratel# than atan().
result = atan$(x(y); result = atan$(x)5.#7);

sinh()

2ind the h#per,olic sine of the value. BPronounced DshineD or DsinchDC


result = sinh(x);

result = sinh(8.@);

cosh()

2ind the h#per,olic cosine of the value.


result = cosh(x); result = cosh(8.@);

tanh()

2ind the h#per,olic tangent of the value.


result = tanh(x); result = tanh(8.@);

%*a#$les
)******************************************************) )* *) )* Jaths functions demo -# *) )* *) )******************************************************) )* use sin(x) to wor6 out an animated model *) -include .stdio.h/ -include .math.h/ -include .limits.h/ -define 3RUB -define 1J,E 3U<B -define ND dou%le pi; # 5@ @.@$ )* this may already %e defined *) )* in the math file *)

)******************************************************) )* Ee4el @ *) )******************************************************) main () 0 pi = asin(#.@)*$; )* 3he simple pendulum program *) )* if , is not defined *)

printf (&2n3HB + J,EB ,BN<UEUJ:2n2n2n&); ,endulum(); A )*****************************************************) )* Ee4el # *) )*****************************************************) ,endulum () 0 dou%le x( twopi = pi * $; int i(position;

while (true) 0 for (x = @; x . twopi; x P= ND) 0 position = (int)(1J,E 3U<B * sin(x)); for (i = -1J,E 3U<B; i .= 1J,E 3U<B; iPP) 0 if (i == position) 0 putchar("*"); A else 0 putchar(" "); A A startofline(); A

A A

)*****************************************************) )* 3ool6it *) )*****************************************************) startofline() 0 putchar("2r"); A

Maths %rrors
)athematical functions can ,e delicate animals. There exist mathematical functions which simpl# cannot produce sensi,le answers in all possi,le cases. )athematical functions are not Duser friendl#D: 1ne example of an unfriendl# function is the inverse sine function asin(x) which onl# wor*s for values of x in the range R%.! to ;%.!. The reason for this is a mathematical one- namel# that the sine function Bof which asin() is the oppositeC onl# has values in this range. The statement
y = asin ($8.5);

is nonsense and it cannot possi,l# produce a value for y, ,ecause none exists. 4imilarl#, there is no simple num,er which is the s8uare root of a negative value, so an expression such asx = sOrt(-$.@);

would also ,e nonsense. This doesn9t stop the programmer from writing these statements though and it doesn9t stop a fault# program from stra#ing out of ,ounds. <hat happens

then when an erroneous statement is executedF 4ome sort of error condition would certainl# have to result. .n man# languages, errors, li*e the ones a,ove, are terminal- the# cause a program to stop without an# option to recover the damage. .n C, as the reader might have come to expect, this is not the case. .t is possi,le Bin principleC to recover from an# error, whilst still maintaining firm control of a program. Errors li*e the ones a,ove are called domain errors Bthe set of values which a function can accept is called the domain of the functionC. There are other errors which can occur too. 2or example, division ,# Aero is illegal, ,ecause dividing ,# Aero is Dmathematical nonsenseD ; it can ,e done, ,ut the answer can ,e all the num,ers which exist at the same time: 1,viousl# a program cannot wor* with an# idea as vague as this. 2inall#, in addition to these DpathologicalD cases, mathematical operations can fail ?ust ,ecause the num,ers the# deal with get too large for the computer to handle, or too small, as the case ma# ,e. Do$ain error .llegal value put into function Di!ision by 6ero 6ividing ,# Aero is nonsense. 1!erflow Num,er ,ecame too large <nderflow Num,er ,ecame too small. 8oss of accuracy No meaningful answer could ,e calculated Errors are investigated ,# calling a function called matherr(). The mathematical functions, listed a,ove, call this function automaticall# when an error is detected. The function responds ,# returning a value which gives information a,out the error. The exact details will depend upon a given compiler. 2or instance a h#pothetical example- if the error could ,e recovered from, matherr() returns !, otherwise it returns ;%. matherr() uses a DstructD t#pe varia,le called an DexceptionD to diagnose faults in mathematical functions, 4ee 4tructures and Unions. This can ,e examined ,# programs which trap their errors dutifull#. .nformation a,out this structure must ,e found in a given compiler manual. 5lthough it is not possi,le to generaliAe, the following remar*s a,out the ,ehaviour of mathematical functions ma# help to avoid an# surprises a,out their ,ehaviour in error conditions.

5 function which fails to produce a sensi,le answer, for an# of the reasons a,ove, might simpl# return Aero or it might return the maximum value of the computer. +e careful to chec* this. B6ivision ,# Aero and underflow pro,a,l# return Aero, whereas overflow returns the maximum value which the computer can handle.C 4ome functions return the value NaN. Not a form of .ndian unleavened ,read, this stands for INot a Num,er9, i.e. no sensi,le result could ,e calculated.

4ome method of signalling errors must clearl# ,e used. This is the exception structure Ba special *ind of C varia,leC which gives information a,out the last error which occurred. 2ind out what it is and trap errors:

1,viousl#, wherever possi,le, the programmer should tr# to stop errors from occurring in the first place.

%*a#$le
7ere is an example for the mathematicall# minded. The program ,elow performs numerical integration ,# the simplest possi,le method of adding up the area under small strips of a graph of the function f(y) = $*y. The integral is found ,etween the limits ! and H and the exact answer is "H. B4ee diagram.C The particular compiler used for this program returns the largest num,er which can ,e represented ,# the computer when num,ers overflow, although, in this simple case, it is impossi,le for the num,ers to overflow.
)**********************************************************) )* *) )* Numerical Bstimation of ntegral *) )* *) )**********************************************************) -include .stdio.h/ -include .math.h/ -include .limits.h/ -define E J 3 8 dou%le inc = @.@@#; dou%le twopi; )* ncrement width - ar%itrary *)

)***********************************************************) )** EBSBE @ *) )***********************************************************) main () 0 dou%le y(integrand(); dou%le integral = @; twopi = 7 * asin(#.@); for ( y = inc)$; y . E J 3; y P= inc ) 0 integral P= integrand (y) * inc; A printf (& ntegral 4alue = '.#@f 2n&(integral); A )***************************************************************) )** EBSBE # **) )***************************************************************) dou%le integrand (y)

dou%le y; 0 dou%le 4alue; 4alue = $*y; if (4alue / #e5@=) 0 printf (&G4erflow error2n&); exit (@); A return (4alue); A

(uestions
%. ". G. . H. <hat t#pe of data is returned from mathematical functionsF 5ll calculations are performed using long varia,les. True or falseF <hat information is returned ,# strlen()F <hat action is performed ,# strcat()F Name five *inds of error which can occur in a mathematical function.

Hidden o$erators and values


*oncise e%pressions )an# operators in C are more versatile than the# appear to ,e, at first glance. Ta*e, for example, the following operators
= PP -P= -= etc...

the assignment, increment and decrement operators... These innocent loo*ing operators can ,e used in some surprising wa#s which ma*e C source code ver# neat and compact. The first thing to notice is that PP and -- are unar# operators- that is, the# are applied to a single varia,le and the# affect that varia,le alone. The# therefore produce one uni8ue value each time the# are used. The assignment operator, on the other hand, has the unusual position of ,eing ,oth unar#, in the sense that it wor*s out onl# one expression, and also ,inar# or d#adic ,ecause it sits ,etween two separate o,?ects- an DlvalueD on the left hand side and an expression on the right hand side. +oth *inds of operator have one thing in common however- ,oth form statements which have values in their own right. <hat does this meanF .t means that certain *inds of statement, in C, do not have to ,e thought of as ,eing complete and sealed off from the rest of a program. To paraphrase a famous author- D.n C, no statement is an islandD. 5 statement can ,e ta*en as a whole Bas a D,lac* ,oxDC and can ,e treated as a single value, which can ,e assigned and compared

to things: The value of a statement is the result of the operation which was carried out in the statement. .ncrementEdecrement operator statements, ta*en as a whole, have a value which is one greater E or one less than the value of the varia,le which the# act upon. 4oc = 8; cPP;

The second of these statement cPP; has the value M, and similarl#c = 8; c--;

The second of these statements c--; has the value . Entire assignment statements have values too. 5 statement such asc = 8;

has the value which is the value of the assignment. 4o the example a,ove has the value H. This has some important implications.

Extended and 7idden QExample "'7idden PP --5rra#s 4trings and 7idden 1peratorsExample "&Cautions a,out 4t#leExample G!>ues "%-

%*tended and Hidden =


The idea that assignment statement has a value, can ,e used to ma*e C programs neat and tid# for one simple reason- it means that a whole assignment statement can ,e used in place of a value. 2or instance, the value c = @; could ,e assigned to a varia,le ,% = (c = @);

or simpl#% = c = @;

These e8uivalent statements set % and c to the value Aero, provided , and c are of the same t#pe: .t is e8uivalent to the more usual% = @; c = @;

.ndeed, an# num,er of these assignments can ,e strung togethera = (% = (c = (d = (e = 8))))

or simpl#a = % = c = d = e = 8;

This ver# neat s#ntax compresses five lines of code into one single line: There are other uses for the valued assignment statement, of course- it can ,e used an#where where a value can ,e used. 2or instance

.n other assignments Bas a,oveC 5s a parameter for functions .nside a comparison BQQ S T etc..C 5s an index for arra#s....

The uses are manifold. Consider how an assignment statement might ,e used as a parameter to a function. The function ,elow gets a character from the input stream stdin and passes it to a function called ,rocessDharacter(),rocessDharacter (ch = getchar());

This is a perfectl# valid statement in C, ,ecause the hidden assignment statement passes on the value which it assigns. The actual order of events is that the assignment is carried out first and then the function is called. .t would not ma*e sense the other wa# around, ,ecause, then there would ,e no value to pass on as a parameter. 4o, in fact, this is a more compact wa# of writingch = getchar(); ,rocessDharacter (ch);

The two methods are entirel# e8uivalent. .f there is an# dou,t, examine a little more of this imaginar# character processing program,rocessDharacter(ch = getchar()); if (ch == "*") 0 printf (&+tarry( +tarry Night...&); A

The purpose in adding the second statement is to impress the fact that ch has ,een assigned 8uite legitimatel# and it is still defined in the next statement and the one after...until it is re;assigned ,# a new assignment statement. The fact that the assignment was hidden inside another statement does not ma*e it an# less valid. 5ll the same remar*s appl# a,out the specialiAed assignment operators P=, *=, )= etc..

%*a#$le
)************************************************) )* *) )* Hidden 1ssignment -# *) )* *) )************************************************) main () 0 do 0 switch (ch = getchar()) 0 default : putchar(ch); %rea6; case "]" : )* ]uit *) A A while (ch I= "]"); A )* end *) )************************************************) )* *) )* Hidden 1ssignment -$ *) )* *) )************************************************) main () 0 dou%le x = @; while ((x P= @.$) . $@.@) 0 printf (&'lf&(x); A A )* end *)

Hidden ++ and -The increment and decrement operators also form statements which have intrinsic values and, li*e assignment expressions, the# can ,e hidden awa# in inconspicuous places.

These two operators are slightl# more complicated than assignments ,ecause the# exist in two forms- as a postfix and as a prefix-ostfi( 4arPP 4ar--refi( PP4ar --4ar

and these two forms have su,tl# different meanings. Loo* at the following exampleint i = 5; ,rintNum%er (iPP);

The increment operator is hidden in the parameter list of the function ,rintNum%er(). This example is not as clear cut as the assignment statement examples however, ,ecause the varia,le i has, ,oth a value ,efore the PP operator acts upon it, and a different value afterwards. The 8uestion is then- which value is passed to the functionF .s i incremented ,efore or after the function is calledF The answer is that this is where the two forms of the operator come into pla#. If the o$erator is used as a $refi*, the o$eration is $erfor#ed before the function call. If the o$erator is used as a $ostfi*, the o$eration is $erfor#ed after the function call. .n the example a,ove, then, the value G is passed to the function and when the function returns, the value of i is incremented to . The alternative is to writeint i = 5; ,rintNum%er (PPi);

in which case the value is passed to the function ,rintNum%er(). The same remar*s appl# to the decrement operator.

3rra,s, /trings and Hidden +$erators


5rra#s and strings are one area of programming in which the increment and decrement operators are used a lot. 7iding operators inside arra# su,scripts or hiding assignments inside loops can often ma*e light wor* of tas*s such as initialiAation of arra#s. Consider the following example of a one dimensional arra# of integers.
-define + FB $@

int i( arrayX+ FBY; for (i = @; i . + FB; arrayXiPPY = @) 0

This is a neat wa# of initialiAing an arra# to Aero. Notice that the postfixed form of the increment operator is used. This prevents the element arrayX@Y from assigning Aero to memor# which is out of the ,ounds of the arra#. 4trings too can ,enefit from hidden operators. .f the standard li,rar# function strlen() Bwhich finds the length of a stringC were not availa,le, then it would ,e a simple matter to write the function
strlen (string) char *string; 0 char *ptr; int count = @; for (ptr = string; *(ptrPP) I= "2@"; countPP) 0 A return (count); A )* count the characters in a string *)

This function increments count while the end of string mar*er 2@ is not found.

%*a#$le
)*********************************************************) )* *) )* Hidden Gperator <emo *) )* *) )*********************************************************) )* 1ny assignment or increment operator has a 4alue *) )* which can %e handed straight to printf() ... *) )* 1lso compare the prefix ) postfix forms of PP)-- *) -include .stdio.h/ )*********************************************************) main () 0 int a(%(c(d(e; a = (% = (c = (d = (e = @)))); printf (&'d 'd 'd 'd 'd2n&( a( %PP( c--( d = #@( e P= 5); a = % = c = d = e = @;

printf (&'d 'd 'd 'd 'd2n&( a( PP%( --c( d = #@( e P= 5); A )* end *) )*******************************************************) )* *) )* Hidden Gperator demo -$ *) )* *) )*******************************************************) -include .stdio.h/ )*******************************************************) main () 0 printf (&'d&(Salue()); A )*******************************************************) Salue() 0 int 4alue; if ((4alue = RetSalue()) == @) 0 printf (&Salue was Nero2n&); A return (4alue); A )********************************************************) RetSalue() 0 return (@); A )* end *) )* +ome function to get a 4alue *) )* Dhec6 for Nero .... *) )* prints out NeroI *)

!autions a out /t,le


7iding operators awa# inside other statements can certainl# ma*e programs loo* ver# elegant and compact, ,ut, as with all neat tric*s, it can ma*e programs harder to understand. Never forget that programming is communication to other programmers and ,e *ind to the potential reader of a program. B.t could ,e #ou in #ears or months to come:C 4tatements such asif ((i = (int)chPP) .= --comparison) 0 A

are not recommenda,le programming st#le and the# are no more efficient than the more longwindedchPP; i = (int)ch; if (i .= comparison) 0 A comparison--;

There is alwa#s a happ# medium in which to settle on a reada,le version of the code. The statement a,ove might perhaps ,e written asi = (int) chPP; if (i .= --comparison) 0 A

%*a#$le
)******************************************************) )* *) )* 1rrays and Hidden Gperators *) )* *) )******************************************************) -include .stdio.h/ -define + FB #@ )******************************************************) )* Ee4el @ *) )******************************************************) main () )* <emo prefix and postfix PP in arrays *)

0 int i( arrayX+ FBY; nitialiNe(array); i = 7; arrayXiPPY = =; ,rint (array); nitialiNe(array); i = 7; arrayXPPiY = =; ,rint(array); A )*******************************************************)

)* Ee4el # *) )*******************************************************) nitialiNe (array) int arrayX+ FBY; 0 int i; for (i = @; i . + FB; arrayXiPPY = @) 0 A A )******************************************************) ,rint (array) int arrayX+ FBY; 0 int i = @; while (i . + FB) 0 printf (&'$d&(arrayXiPPY); A putchar ("2n"); A )* end *) )****************************************************) )* *) )* Hidden Gperator *) )* *) )****************************************************) -include .stdio.h/ -define J1CNG $@ )* to stdout *) )* set to Nero *)

)*****************************************************) main () 0 int i( ctr = @; for (i = #; PPctr .= J1CNG; i = ctr*8) 0 printf (&'5d&(i); A A )* ,rint out 8 x ta%le *)

(uestions
%. <hich operators can ,e hidden inside other statementsF

". Give a reason wh# #ou would not want to do this in ever# possi,le case. G. 7idden operators can ,e used in return statements .e.g
7. 8. return (PPx);

<ould there ,e an# point in writingreturn (xPP);

More on data t,$es


This section is a,out the remaining data t#pes which C has to offer programmers. 4ince C allows #ou to define new data t#pes we shall not ,e a,le to cover all of the possi,lities, onl# the most important examples. The most important of these are
L EB

The t#pe which files are classified under


enum 4oid

Enumerated t#pe for a,stract data The Dempt#D t#pe

4olatile const struct union

New 5N4. standard t#pe for memor# mapped .E1 New 5N4. standard t#pe for fixed data Groups of varia,les under a single name )ulti;purpose storage areas for d#namical memor# allocation

4pecial Constant Expressions2.LEenumExample G%Example G"4uggested uses for enumvoidvolatileconststruct againuniont#pedef>uestions "G-

/$ecial !onstant %*$ressions

Constant expressions are often used without an# thought, until a programmer needs to *now how to do something special with them. .t is worth ma*ing a ,rief remar* a,out some special wa#s of writing integer constants, for the latter half of this ,oo*. Up to now the distinction ,etween long and short integer t#pes has largel# ,een ignored. Constant values can ,e declared explicitl# as long values, in fact, ,# placing the letter E after the constant.
long int 4aria%le = $5E; 4aria%le = $5:8$:8>=E;

5dvanced programmers, writing s#stems software, often find it convenient to wor* with hexadecimal or octal num,ers since these num,er ,ases have a special relationship to ,inar#. 5 constant in one of these t#pes is declared ,# placing either @ BAeroC or @x in front of the appropriate value. .f ddd is a value, thenGctal num%er Hexadecimal num%er @ddd @xddd

2or exampleoctK4alue = @;;; hexK4alue = @xLLBL; )* ;; octal *) )* LLBL hex *)

This *ind of notation has alread# ,een applied to strings and single character constants with the ,ac*slash notation, instead of the leading Aero characterch = "2ddd"; ch = "2xdd";

The values of character constants, li*e these, cannot ,e an# greater than "HH.
FILE

.n all previous sections, the files stdin, stdout and stderr alone have ,een used in programs. These special files are alwa#s handled implicitl# ,# functions li*e printf() and scanf()- the programmer never gets to *now that the# are, in fact, files. Programs do not have to use these functions however- standard inputEoutput files can ,e treated explicitl# ,# general file handling functions ?ust as well. 2iles are distinguished ,# filenames and ,# file pointers. 2ile pointers are varia,les which pass the location of files to file handling functions@ ,eing varia,les, the# have to ,e declared as ,eing some data t#pe. That t#pe is called L EB and file pointers have to ,e declared Dpointer to L EBD. 2or exampleL EB *fp;

L EB *fp = stdin; L EB *fopen();

2ile handling functions which return file pointers must also ,e declared as pointers to files. Notice that, in contrast to all the other reserved words L EB is written in upper casethe reason for this is that L EB is not a simple data t#pe such as char or int, ,ut a structure which is onl# defined ,# the header file stdio.h and so, strictl# spea*ing, it is not a reserved word itself. <e shall return to loo* more closel# at files soon.
enum

5,stract data are usuall# the realm of exclusivel# high level languages such as Pascal. enum is a wa# of incorporating limited Dhigh levelD data facilities into C. is short for enumerated data. The user defines a t#pe of data which is made up of a fixed set of words, instead of num,ers or characters. These words are given su,stitute integer num,ers ,# the compiler which are used to identif# and compare enum t#pe data. 2or exampleenum enum countries 0 Bngland( +cotland( ?ales( Bire( Norge( +4erige( <anmar6( <eutschland A; main () 0 enum countries 4aria%le; 4aria%le = Bngland; A

<h# go to all this trou,leF The point a,out enumerated data is that the# allow the programmer to forget a,out an# num,ers which the computer might need in order to deal with a list of words, li*e the ones a,ove, and simpl# concentrate on the logic of using them. Enumerated data are called a,stract ,ecause the low level num,er form of the words is removed from the users attention. .n fact, enumerated data are made up of integer constants, which the compiler generates itself. 2or this reason, the# have a natural partner in programs- the switch statement. 7ere is an example, which uses the countries a,ove to ma*e a *ind of airport Dhelp computerD in age of electronic passports:

%*a#$le
)**********************************************************) )* *) )* Bnumerated <ata *) )* *) )**********************************************************) -include .stdio.h/ enum countries 0 Bngland( reland( +cotland( ?ales( <anmar6( sland( Norge( +4erige A; )**********************************************************) main () )* Blectronic ,assport ,rogram *)

0 enum countries %irthplace( getinfo(); printf (& nsert electronic passport2n&); %irthplace = getinfo(); switch (%irthplace) 0 case Bngland : printf (&?elcome homeI2n&); %rea6; case <anmar6 : case Norge : printf (&Sel6ommen til Bngland2n&); %rea6; A A )************************************************************) enum countries getinfo() 0 return (Bngland); A )* end *) )* interrogate passport *)

ma*es words into constant integer values for a programmer. 6ata which are declared enum are not the *ind of data which it ma*es sense to do arithmetic with Beven integer arithmeticC, so in most cases it should not ,e necessar# to *now or even care a,out what num,ers the compiler gives to the words in the list. 7owever, some compilers
enum

allow the programmer to force particular values on words. The compiler then tries to give the values successive integer num,ers unless the programmer states otherwise. 2or instanceenum planets 0 Jercury( Senus( Barth = #$( Jars( ^upiter( +aturn( Uranus( Neptune( ,luto A;

This would pro,a,l# #ield values Jercury = @, Senus = #, Barth = #$, Jars = #5, ^upiter = #7 ... etc. .f the user tries to force a value which the compiler has alread# used then the compiler will complain. The following example program listing shows two points

t#pes can ,e local or glo,al. The la,els can ,e forced to have certain values
enum

%*a#$le
)**********************************************************) )* *) )* Bnumerated <ata *) )* *) )**********************************************************) )* 3he smallest ad4enture game in the world *) -include .stdio.h/ -define 3RUB # -define L1E+B @ enum treasures 0 ru%ies( sapphires( gold( sil4er( mas6( scroll( lamp A; )* 1d4enture 3reasures *)

)***********************************************************) )* Ee4el @ *) )***********************************************************)

main () 0 enum treasures o%Uect = gold;

)* 3iny 1d4entureI *)

if (geto%Uect(o%Uect)) 0 printf (&Dongratulations you"4e found the goldI2n&); A else 0 printf (&3oo %ad -- you Uust missed your %ig chance&); A A )***********************************************************) )* Ee4el # *) )***********************************************************) geto%Uect (o%) enum treasures o%; 0 enum answer 0 no = false( yes = true A; if (o% == gold) 0 printf (&,ic6 up o%UectV \)N2n&); switch (getchar()) 0 case "y" : case "\" : return ((int) yes); )* true and false *) default : return ((int) no); )* are integers *) A A else 0 printf (&\ou grapple with the dirt2n&); return (false); A A )* end *) )* yes or no V *)

/uggested uses for enu#


7ere are some suggested uses for enum.
enum num%ers 0 Nero(

one( two( three A; enum animals 0 cat( dog( cow( sheep( A; enum plants 0 grass( roses( ca%%ages( oa6tree A; enum diseases 0 heart( s6in( malnutrition( circulatory A; enum Ouar6s 0 up( down( charmed( strange( top( %ottom( truth( %eauty A;

1ther suggestions- colours, names of roads or t#pes of train.


oid

is a peculiar data t#pe which has some de,ata,le uses. The void datat#pes was introduced in order to ma*e C s#ntacticall# consistent. The main idea of 4oid is to ,e a,le to declare functions which have no return value. The word Ivoid9 is intended in the meaning Iempt#9 rather than Iinvalid9. .f #ou recall, the default is for C functions to return a value of t#pe int. The value returned ,# a function did not ha!e to ,e specified could alwa#s ,e discarded, so this was not a pro,lem in practice. .t did ma*e compiler chec*s more difficult however- how do #ou warn someone a,out inconsistent return values if it is legal to ignore return valuesF
4oid

The 5N4. solution was to introduce a new data t#pe which was called 4oid for functions with no value. The word 4oid is perhaps an unfortunate choice, since it has several implicit meanings none of which reall# express what is intended. The words Inovalue9 or Inot#pe9 would have ,een ,etter choices. 5 varia,le or function can ,e declared 4oid in the following wa#s.
4oid function(); 4oid 4aria%le; 4oid *ptr; (4oid) return4alue();

The following are true of 4oid

5 varia,le which is declared 4oid is useless- it cannot ,e used in an expression and it cannot ,e assigned to a value. The data t#pe was introduced with functions in mind ,ut the grammar of C allows us to define varia,les of this t#pe also, even though there is no point. 5 function which is declared 4oid has no return value and returns simpl# withreturn;

5 function call can ,e cast (4oid) in order to explicitl# discard a return value Bthough this is done ,# the compiler an#wa#C. 2or instance, scanf() returns the num,er of items it matches in the control string, ,ut this is usuall# discarded.
scanf (&'c&(Mch);

or
(4oid) scanf(&'c&(Mch);

2ew programmers would do this since it merel# clutters up programs with irrelevant ver,iage.

5 4oid pointer can point to to an# *ind of o,?ect. This means that an# pointer can ,e assigned to a 4oid pointer, regardless of its t#pe. This is also a highl# 8uestiona,le feature of the 5N4. draft. .t replaces the meaning of 4oid from Ino t#pe or value9 to Ino particular t#pe9. .t allows assignments ,etween incompati,le pointer t#pes without a cast operator. This is also rather du,ious.

olatile

is a t#pe which has ,een proposed in the 5N4. standard. The idea ,ehind this t#pe is to allow memor# mapped inputEoutput to ,e held in C varia,les. 3aria,les which are declared volatile will ,e a,le to have their values altered in wa#s which a program does not explicitl# define- that is, ,# external influences such as cloc*s, external ports, hardware, interrupts etc...
4olatile

The 4olatile datat#pe has found another use since the arrival of multiprocessor, multithreaded operating s#stems. .ndependent processes which share common memor# could each change a varia,le independentl#. .n other words, in a multithreaded environment the value of a varia,le set ,# one process in shared memor# might ,e altered ,# another process without its *nowledge. The *e#word 4olatile servers as a warning to the compiler that an# optimiAing code it produces should not rel# on caching the value of the varia,le, it should alwa#s reread its value.
const

The reserved word const is used to declare data which can onl# ,e assigned once, either ,ecause the# are in /1) Bfor exampleC or ,ecause the# are data whose values must not ,e corrupted. T#pes declared const must ,e assigned when the# are first initialiAed and the# exist as stored values onl# at compile timeconst dou%le pi = 5.#7; const int one = #;

4ince a constant arra# onl# exists at compile time, it can ,e initialiAed ,# the compiler.
const int arrayXY = 0 #( $( 5( 7 A;

then has the value %, arrayX#Y has the value " ... and so on. 5n# attempt to assign values to const t#pes will result in compilation errors.
arrayX@Y

.t is worth comparing the const declaration to enumerated data, since the# are connected in a ver# simple wa#. The following two sets of of statements are the sameenum num%ers 0 Nero( one( two( three( four A;

and
const const const const const Nero = @; one = #; two = $; three = 5; four = 7;

Constant t#pes and enumerated data are therefore ?ust different aspects of the same thing. Enumerated data provide a convenient wa# of classif#ing constants, however, while the compiler *eeps trac* of the values and t#pes. <ith const #ou have to *eep trac* of constant values personall#.
struct

4tructures are called records in Pascal and man# other languages. The# are pac*ages of varia,les which are all wrapped up under a single name. 4tructures are descri,ed in detail in chapter "H.
union

Unions are often grouped together with structures, ,ut the# are 8uite unli*e them in almost all respects. The# are li*e general purpose storage containers, which can hold a variet# of different varia,le t#pes, at different times. The compiler ma*es a container which is large enough to ta*e an# of these, 4ee 4tructures and Unions.
t!pedef

C allows us to define our own data t#pes or to rename existing ones ,# using a compiler directive called typedef. This statement is used as followstypedef type newtypename;

4o, for example, we could define a t#pe called %yte, which was exactl# one ,#te in siAe ,# redefining the word chartypedef unsigned char %yte;

The compiler t#pe chec*ing facilities then treat ,#te as a new t#pe which can ,e used to declare varia,les%yte 4aria%le( function();

The t#pedef statement ma# ,e written inside functions or in the glo,al white space of a program.
)**************************************************) )* ,rogram *) )**************************************************) typedef int newname#; main ()

0 typedef char newname$; A

This program will compile and run Bthough it will not do ver# muchC. .t is not ver# often that #ou want to rename existing t#pes in the wa# shown a,ove. The most important use for t#pedef is in con?unction with structures and unions. 4tructures and unions can, ,# their ver# definition, ,e all *inds of shape and siAe and their names can ,ecome long and tedious to declare. t#pedef ma*es dealing with these simple ,ecause it means that the user can define a structure or union with a simple t#pename.

(uestions
%. .s L EB a reserved wordF .f so wh# is it in upper caseF ". <rite a statement which declares a file pointer called fp. G. Enumerated data are given values ,# the compiler so that it can do arithmetic with them. True or falseF . 6oes 4oid do an#thing which C cannot alread# do without this t#peF H. <hat t#pe might a timer device ,e declared if it were to ,e called ,# a varia,le nameF M. <rite a statement which declares a new t#pe DrealD to ,e li*e the usual t#pe Ddou,leD. (. 3aria,les declared const can ,e of an# t#pe. True or falseF

Machine Level +$erations


9its and 9ytes. 3lags=$essages. Shifting. 6own in the depths of #our computer, ,elow even the operating s#stem are ,its of memor#. These da#s we are used to wor*ing at such a high level that it is eas# to forget them. +its Bor ,inar# digitsC are the lowest level software o,?ects in a computer- there is nothing more primitive. 2or precisel# this reason, it is rare for high level languages to even ac*nowledge the existence of ,its, let alone manipulate them. )anipulating ,it patterns is usuall# the preserve of assem,l# language programmers. C, however, is 8uite different from most other high level languages in that it allows a programmer full access to ,its and even provides high level operators for manipulating them. 4ince this ,oo* is an introductor# text, we shall treat ,it operations onl# superficiall#. )an# of the facilities which are availa,le for ,it operations need not concern the ma?orit# of programs at all. This section concerns the main uses of ,it operations for high level programs and it assumes a certain amount of *nowledge a,out programming at the low level. =ou ma# wish to consult a ,oo* on assem,l# language programming to learn a,out low level memor# operations, in more detail.

+it Patterns-

2lags registers+it 1perators and 5ssignments+it operators4hift 1perationsTruth Ta,les and )as*ingExample GG1utput GGExample G Example GH>uestions " -

Bit Patterns
5ll computer data, of an# t#pe, are ,it patterns. The onl# difference ,etween a string and a floating point varia,le is the wa# in which we choose to interpret the patterns of ,its in a computer9s memor#. 2or the most part, it is 8uite unnecessar# to thin* of computer data as ,it patterns@ s#stems programmers, on the other hand, fre8uentl# find that the# need to handle ,its directl# in order to ma*e efficient use of memor# when using flags. 5 flag is a message which is either one thing or the other- in s#stem terms, the flag is said to ,e Ion9 or Ioff9 or alternativel# set or cleared. The usual place to find flags is in a status register of a CPU Bcentral processor unitC or in a pseudo;register Bthis is a status register for an imaginar# processor, which is held in memor#C. 5 status register is a group of ,its Ba ,#te perhapsC in which each ,it signifies something special. .n an ordinar# ,#te of data, ,its are grouped together and are interpreted to have a collective meaning@ in a status register the# are thought of as ,eing independent. Programmers are interested to *now a,out the contents of ,its in these registers, perhaps to find out what happened in a program after some special operation is carried out. 1ther uses for ,it patterns are listed ,elow here

)essages sent ,etween devices in a complex operating environment use ,its for efficienc#. 4eriall# transmitted data. 7andling ,it;planes in screen memor#. B/aster ports and devicesC Performing fast arithmetic in simple cases.

Programmers who are interested in performing ,it operations often wor* in hexadecimal ,ecause ever# hexadecimal digit convenientl# handles four ,its in one go B%M is " to the power C.

-lags, )egisters and Messages


5 register is a place inside a computer processor chip, where data are wor*ed upon in some wa#. 5 status register is a register which is used to return information to a programmer a,out the operations which too* place in other registers. 4tatus registers contain flags which give #es or no answers to 8uestions concerning the other registers. .n advanced programming, there ma# ,e call for Dpseudo registersD in addition to DrealD ones. 5 pseudo register is merel# a register which is created ,# the programmer in computer memor# Bit does not exist inside a processorC.

)essages are ?ust li*e pseudo status registers- the# are collections of flags which signal special information ,etween different devices andEor different programs in a computer s#stem. )essages do not necessaril# have fixed locations- the# ma# ,e passed a parameters. )essages are a ver# compact wa# of passing information to low level functions in a program. 2lags, registers, pseudo;registers and messages are all treated as ,it patterns. 5 program which ma*es use of them must therefore ,e a,le to assign these o,?ects to C varia,les for use. 5 ,it pattern would normall# ,e declared as a character or some *ind of integer t#pe in C, perhaps with the aid of a t#pedef statement.
typedef char %yte; typedef int %itpattern; %itpattern 4aria%le; %yte message;

The flags or ,its in a registerEmessage... have the values % or !, depending upon whether the# are on or off Bset or clearedC. 5 program can test for this ,# using com,inations of the operators which C provides.

Bit +$erators and 3ssign#ents


C provides the following operators for handling ,it patterns..

+it shift left Ba specified num,er or ,it positionsC


// Q Z M [ M= Q= Z= //= ..=

+it shift rightBa specified num,er of ,it positionsC +itwise .nclusive 1/ +itwise Exclusive 1/ +itwise 5N6 +itwise one9s complement 5N6 assign Bvaria,le Q varia,le 0 valueC Exclusive 1/ assign Bvaria,le Q varia,le U valueC .nclusive 1/ assign Bvaria,le Q varia,le V valueC 4hift right assign Bvaria,le Q varia,le SS valueC 4hift left assign Bvaria,le Q varia,le TT valueC

The meaning and the s#ntax of these operators is given ,elow.

"he Meaning of Bit +$erators


+itwise operations are not to ,e confused with logical operations BMM, QQ...C 5 ,it pattern is made up of !s and %s and ,itwise operators operate individuall# upon each ,it in the operand. Ever# ! or % undergoes the operations individuall#. +itwise operators B5N6, 1/C can ,e used in place of logical operators BMM,QQC, ,ut the# are less efficient, ,ecause logical operators are designed to reduce the num,er of comparisons made, in an expression, to the optimum- as soon as the truth or falsit# of an expression is *nown, a logical comparison operator 8uits. 5 ,itwise operator would continue operating to the last ,efore the final result were *nown. +elow is a ,rief summar# of the operations which are performed ,# the a,ove operators on the ,its of their operands.

/hift +$erations
.magine a ,it pattern as ,eing represented ,# the following group of ,oxes. Ever# ,ox represents a ,it@ the num,ers inside represent their values. The values written over the top are the common integer values which the whole group of ,its would have, if the# were interpreted collectivel# as an integer.
#$= :7 5$ #: = 7 $ # = #

------------------------------Q @ Q @ Q @ Q @ Q @ Q @ Q @ Q # Q -------------------------------

4hift operators move whole ,it patterns left or right ,# shunting them ,etween ,oxes. The s#ntax of this operation is4alue .. num%er of positions 4alue // num%er of positions

4o for example, using the ,oxed value B%C a,ove# .. #

would have the value ", ,ecause the ,it pattern would have ,een moved one place the the left#$= :7 5$ #: = 7 $ # = $

------------------------------Q @ Q @ Q @ Q @ Q @ Q @ Q # Q @ Q -------------------------------

4imilarl## .. 7

has the value %M ,ecause the original ,it pattern is moved ,# four places#$= :7 5$ #: = 7 $ # = #:

------------------------------Q @ Q @ Q @ Q # Q @ Q @ Q @ Q @ Q -------------------------------

5nd: .. $ == #$ #$= :7 5$ #: = 7 $ # = :

------------------------------Q @ Q @ Q @ Q @ Q @ Q # Q # Q @ Q -------------------------------

4hift left " places#$= :7 5$ #: = 7 $ # = #$

------------------------------Q @ Q @ Q @ Q @ Q # Q # Q @ Q @ Q -------------------------------

Notice that ever# shift left multiplies ,# " and that ever# shift right would divide ,# two, integerwise. .f a ,it reaches the edge of the group of ,oxes then it falls out and is lost forever. 4o# $ $ n // // // // # # $ n == == == == @ # @ @

5 common use of shifting is to scan through the ,its of a ,itpattern one ,# one in a loopthis is done ,# using $asks.

"ruth "a les and Masking


The operations 5N6, 1/ Binclusive 1/C and W1/EE1/ Bexclusive 1/C perform comparisons or Dmas*ingD operations ,etween two ,its. The# are ,inar# or d#adic operators. 5nother operation called C1)PLE)ENT is a unar# operator. The operations performed ,# these ,itwise operators are ,est summariAed ,# truth tables. Truth ta,les indicate what the results of all possi,le operations are ,etween two single ,its. The same operation is then carried out for all the ,its in the varia,les which are operated upon.

Complement X-

5N61/W1/-

!o#$le#ent "
The complement of a num,er is the logical opposite of the num,er. C provides a Done9s complementD operator which simpl# changes all %s into !s and all !s into %s.
[# has the 4alue @ [@ has the 4alue # (for each %it)

5s a truth ta,le this would ,e summariAed as follows[value @ # == # @ result

Node-5N6, Next-1/, Previous-Complement X, Up-Truth Ta,les and )as*ing

36' &
This wor*s ,etween two values. e.g. B# M @C
value 1 @ @ # # M value 2 @ # @ # == result @ @ @ #

+oth value % 5N6 value " have to ,e % in order for the result or ,e %. Node-1/, Next-W1/, Previous-5N6, Up-Truth Ta,les and )as*ing

+) #
This wor*s ,etween two values. e.g. B# Q @C
value 1 @ @ # # Q value 2 @ # @ # == result @ # # #

The result is % if one 1/ the other 1/ ,oth of the values is %. Node-W1/, Previous-1/, Up-Truth Ta,les and )as*ing

;+):%+) $
1perates on two values. e.g. B# Z @C
value 1 @ @ # # Z value 2 @ # @ # == result @ # # @

The result is % if one 1/ the other B,ut not ,othC of the values is %. +it patterns and logic operators are often used to ma*e $asks. 5 mas* is as a thing which fits over a ,it pattern and modifies the result in order perhaps to single out particular ,its, usuall# to cover up part of a ,it pattern. This is particularl# pertinent for handling flags, where a programmer wishes to *now if one particular flag is set or not set and does not care a,out the values of the others. This is done ,# deli,eratel# inventing a value which onl# allows the particular flag of interest to have a non;Aero value and then 5N6ing that value with the flag register. 2or example- in s#m,olic languageJ1+W = @@@@@@@# S1EUB# = #@@##@## S1EUB$ = #@@###@@ J1+W M S1EUB# == @@@@@@@# J1+W M S1EUB$ == @@@@@@@@

The Aeros in the mas* $asks off the first seven ,its and leave onl# the last one to reveal its true value. 5lternativel#, mas*s can ,e ,uilt up ,# specif#ing several flagsLE1R# = @@@@@@@# LE1R$ = @@@@@@#@ LE1R5 = @@@@@#@@ JB++1RB = LE1R# Q LE1R$ Q LE1R5 JB++1RB == @@@@@###

.t should ,e emphasiAed that these expressions are onl# written in s#m,olic language- it is not possi,le to use ,inar# values in C. The programmer must convert to hexadecimal, octal or denar# first. B4ee the appendices for conversion ta,lesC.

%*a#$le
5 simple example helps to show how logical mas*s and shift operations can ,e com,ined. The first program gets a denar# num,er from the user and converts it into

,inar#. The second program gets a value from the user in ,inar# and converts it into hexadecimal.
)***************************************************) )* *) )* 9it Janipulation -# *) )* *) )***************************************************) )* )* )* )* Don4ert denary num%ers into %inary *) Weep shifting i %y one to the left *) and test the highest %it. 3his does*) NG3 preser4e the 4alue of i *) =

-include .stdio.h/ -define NUJ9BRGL9 3+

)****************************************************) main () 0 short i(U(%it(; short J1+W = @x=@; printf (&Bnter any num%er less than #$=: &); scanf (&'h&( Mi); if (i / #$=) 0 printf (&3oo %ig2n&); return (@); A printf (&9inary 4alue = &); for (U = @; U . NUJ9BRGL9 3+; UPP) 0 %it = i M J1+W; printf (&'#d&(%it)J1+W); i ..= #; A printf (&2n&); A )* end *)

+ut$ut
Bnter any num%er less than #$=: 8: 9inary 4alue = @@###@@@ Bnter any 4alue less than #$=: 5 9inary 4alue = @@@@@@##

%*a#$le

)***************************************************) )* *) )* 9it Janipulation -$ *) )* *) )***************************************************) )* Don4ert %inary num%ers into hex -include .stdio.h/ -define NUJ9BRGL9 3+ = )****************************************************) main () 0 short U(hex = @; short J1+W; char %inaryXNUJ9BRGL9 3+Y; printf (&Bnter an =-%it %inary num%er: &); for (U = @; U . NUJ9BRGL9 3+; UPP) 0 %inaryXUY = getchar(); A for (U = @; U . NUJ9BRGL9 3+; UPP) 0 hex ..= #; switch (%inaryXUY) 0 case "#" : J1+W = #; %rea6; case "@" : J1+W = @; %rea6; default : printf(&Not %inary2n&); return(@); A hex Q= J1+W; A printf (&Hex 4alue = '#x2n&(hex); A )* end *) *)

%*a#$le
Bnter any num%er less than #$=: 8: 9inary 4alue = @@###@@@ Bnter any 4alue less than #$=: 5 9inary 4alue = @@@@@@##

(uestions

%. <hat distinguishes a ,it pattern from an ordinar# varia,leF Can an# varia,le ,e a ,it patternF ". <hat is the difference ,etween an inclusive 1/ operation and an exclusive 1/ operationF G. .f #ou saw the following function call in a program, could #ou guess what its parameter wasF
7. Gpen?indow (9GR<BR Q R1<RB3+ Q JGU+BDGN3RGE Q + F NR); 8.

M. 2ind out what the denar# BdecimalC values of the following operations are%. ; M $ ". # M # G. #8 M 5 . #8 M ; H. #8 M ; M 5 Tr# to explain the results. B7int- draw out the num,ers as ,inar# patterns, using the program listed.C (. 2ind out what the denar# BdecimalC values of the following operations are%. # Q $ ". # Q $ Q 5 '. 2ind out the values of%. # M ([#) ". $5 M ([$5) G. $@#$ M ([$@#$) B7int- write a short program to wor* them out. Use short t#pe varia,les for all the num,ersC.

-iles and 'evices


2iles are places for reading data from or writing data to. This includes dis* files and it includes devices such as the printer or the monitor of a computer. C treats all information which enters or leaves a program as though it were a stream of ,#tes- a file. The most commonl# used file streams are stdin Bthe *e#,oardC and stdout Bthe screenC, ,ut more sophisticated programs need to ,e a,le to read or write to files which are found on a dis* or to the printer etc. 5n operating s#stem allows a program to see files in the outside world ,# providing a num,er of channels or Iportals9 BIinlets9 and Ioutlets9C to wor* through. .n order to examine the contents of a file or to write information to a file, a program has to open one of these portals. The reason for this slightl# indirect method of wor*ing is that channelsEportals hide operating s#stem dependent details of filing from the programmer. Thin* of it as a protocol. 5 program which writes information does no more than pass that information to one of these portals and the operating s#stem9s filing su,s#stem does the rest. 5 program which reads data simpl# reads values from its file portal and does not

have to worr# a,out how the# got there. This is extremel# simple to wor* in practice. To use a file then, a program has to go through the following routine

1pen a file for reading or writing. B/eserve a portal and locate the file on dis* or whatever.C /ead or write to the file using file handling functions provided ,# the standard li,rar#. Close the file to free the operating s#stem DportalD for use ,# another program or file.

5 program opens a file ,# calling a standard li,rar# function and is returned a file pointer, ,# the operating s#stem, which allows a program to address that particular file and to distinguish it from all others.

2iles Generall#2ile Positions7igh Level 2ile 7andling 2unctions1pening filesClosing a filefprintffscanfs*ipfilegar,F4ingle Character .E1getc and fgetcungetcputc and fputcfgets and fputsfeofPrinter 1utputExample GM1utput GMConverting example2ile Errors1ther 2acilities for 7igh Level 2ilesfreadBC and fwriteBCftell and fsee*rewindfflushLow Level 2iling 1perations2ile 7andlesopenclosecreatreadwritelsee*unlin* remove-

Example G(>uestions "H-

-iles 5enerall,
C provides two levels of file handling@ these can ,e called high level and low level. 7igh level files are all treated as text files. .n fact, the data which go into the files are exactl# what would ,e seen on the screen, character ,# character, except that the# are stored in a file instead. This is true whether a file is meant to store characters, integers, floating point t#pes. 5n# file, which is written to ,# high level file handling functions, ends up as a text file which could ,e edited ,# a text editor.

7igh level text files are also read ,ac* as character files, in the same wa# that input is ac8uired from the *e#,oard. This all means that high level file functions are identical in concept to *e#,oardEscreen inputEoutput. The alternative to these high level functions, is o,viousl# low level functions. These are more efficient, in principle, at filing data as the# can store data in large lumps, in raw memor# format, without converting to text files first. Low level inputEoutput functions have the disadvantage that the# are less Iprogrammer friendl#9 than the high level ones, ,ut the# are li*el# to wor* faster.

2ile Positions7igh Level 2ile 7andling 2unctions1pening files-

Closing a filefprintffscanfs*ipfilegar,F4ingle Character .E1getc and fgetcungetcputc and fputcfgets and fputsfeofConverting example2ile Errors1ther 2acilities for 7igh Level 2ilesfreadBC and fwriteBCftell and fsee*rewindfflushLow Level 2iling 1perations2ile 7andlesopenclosecreatreadwritelsee*unlin* remove-

-ile Positions
<hen data are read from a file, the operating s#stem *eeps trac* of the current position of a program within that file so that it onl# needs to ma*e a standard li,rar# call to Iread the next part of the file9 and the operating s#stem o,liges ,# reading some more and advancing its position within the file, until it reaches the end. Each single character which is read causes the position in a file to ,e advanced ,# one. 5lthough the operating s#stem does a great deal of hand holding regarding file positions, a program can control the wa# in which that position changes with functions such as ungetc() if need ,e. .n most cases it is not necessar# and it should ,e avoided, since complex movements within a file can cause complex movements of a dis* drive mechanism which in turn can lead to wear on dis*s and the occurrence of errors.

High Level -ile Handling -unctions


)ost of the high level inputEoutput functions which deal with files are easil# recogniAa,le in that the# start with the letter If9. 4ome of these functions will appear stri*ingl# familiar. 2or instance-

fprintf() fscanf() fgets() fputs()

These are all generaliAed file handling versions of the standard inputEoutput li,rar#. The# wor* with generaliAed files, as opposed to the specific files stdin and stdout which printf() and scanf() use. The file versions differ onl# in that the# need an extra piece of information- the file pointer to a particular portal. This is passed as an extra parameter to the functions. the# process data in an identical wa# to their standard .E1 counterparts. 1ther filing functions will not loo* so familiar. 2or examplefopen() fclose() getc() ungetc(); putc() fgetc() fputc() feof()

+efore an# wor* can ,e done with high level files, these functions need to ,e explained in some detail.

+$ening files
5 file is opened ,# a call to the li,rar# function fopen()- this is availa,le automaticall# when the li,rar# file Tstdio.hS is included. There are two stages to opening a file- firstl# a file portal must ,e found so that a program can access information from a file at all. 4econdl# the file must ,e ph#sicall# located on a dis* or as a device or whatever. The fopen() function performs ,oth of these services and, if, in fact, the file it attempts to open does not exist, that file is created anew. The s#ntax of the fopen() function isL EB *returnpointer; returnpointer = fopen(&filename&(&mode&);

or
L EB returnpointer; char *fname( *mode; returnpointer = fopen(fname(mode);

The filename is a string which provides the name of the file to ,e opened. 2ilenames are s#stem dependent so the details of this must ,e sought from the local operating s#stem manual. The operation mode is also a string, chosen from one of the following-

r w a rw

1pen file for reading 1pen file for writing 1pen file for appending 1pen file for reading and writing Bsome s#stemsC

This mode string specifies the wa# in which the file will ,e used. 2inall#, returnpointer is a pointer to a L EB structure which is the whole o,?ect of calling this function. .f the file Bwhich was namedC opened successfull# when fopen() was called, returnpointer is a pointer to the file portal. .f the file could not ,e opened, this pointer is set to the value NUEE. This should ,e tested for, ,ecause it would not ma*e sense to attempt to write to a file which could not ,e opened or created, for whatever reason. 5 read onl# file is opened, for example, with some program code such asL EB *fp; if ((fp = fopen (&filename&(&r&)) == NUEE) 0 printf (&Lile could not %e opened2n&); errorKhandler(); A

5 8uestion which springs to mind is- what happens if the user has to t#pe in the name of a file while the program is runningF The solution to this pro,lem is 8uite simple. /ecall the function filename() which was written in chapter "!.
char *filename() )* return filename *)

0 static char *filenm = &........................&; do 0 printf (&Bnter filename :&); scanf (&'$7s&(filenm); s6ipgar%(); A while (strlen(filenm) == @); return (filenm); A

This function ma*es file opening simple. The programmer would now write something li*eL EB *fp; char *filename(); if ((fp = fopen (filename()(&r&)) == NUEE)

0 printf (&Lile could not %e opened2n&); errorKhandler(); A

and then the user of the program would automaticall# ,e prompted for a filename. 1nce a file has ,een opened, it can ,e read from or written to using the other li,rar# functions Bsuch as fprintf() and fscanf()C and then finall# the file has to ,e closed again.

!losing a file
5 file is closed ,# calling the function fclose(). fclose() has the s#ntaxint returncode; L EB *fp; returncode = fclose (fp);

is a pointer to the file which is to ,e closed and returncode is an integer value which is ! if the file was closed successfull#. fclose() prompts the file manager to finish off its dealings with the named file and to close the portal which the operating s#stem reserved for it. <hen closing a file, a program needs to do something li*e the followingfp if (fclose(fp) I= @) 0 printf (&Lile did not exist.2n&); errorKhandler(); A fprintf()

This is the highest level function which writes to files. .ts name is meant to signif# Dfile; print;formattedD and it is almost identical to its stdout counterpart printf(). The form of the fprintf() statement is as followsfprintf (fp(&string&(4aria%les);

where fp is a file pointer, string is a control string which is to ,e formatted and the varia,les are those which are to ,e su,stituted into the ,lan* fields of the format string. 2or example, assume that there is an open file, pointed to ,# fpint i = #$; float x = $.58:; char ch = "s";

fprintf (fp( &'d 'f 'c&( i( x( ch);

The conversion specifiers are identical to those for printf(). .n fact fprintf() is related to printf() in a ver# simple wa#- the following two statements are identical.
printf (&Hello world 'd&( #); fprintf (stdout(&Hello world 'd&( #);

fscanf()

The analogue of scanf() is fscanf() and, as with fprintf(), this function differs from its standard .E1 counterpart onl# in one extra parameter- a file pointer. The form of an fscanf() statement isL EB *fp; int n; n = fscanf (fp(&string&(pointers);

where n is the num,er of items matched in the control string and fp is a pointer to the file which is to ,e read from. 2or example, assuming that fp is a pointer to an open fileint i = #@; float x = -$.58:; char ch = "x"; fscanf (fp( &'d 'f 'c&( Mi( Mx( Mch);

The remar*s which were made a,out scanf() also appl# to this function- fscanf() is a Idangerous9 function in that it can easil# get out of step with the input data unless the input is properl# formatted.

ski$filegar <= 8
6o programs need a function such as s6ipgar%() to deal with instances of ,adl# formatted input dataF 5 programmer can assume a ,it more a,out files which are read into a program from dis* file than it can assume a,out the user9s t#ped input. 5 dis* file will presuma,l# have ,een produced ,# the same program which generated it, or will ,e in a format which the program expects. .s a function li*e s6ipgar%() necessar# thenF The answer is- pro,a,l# not. This does not mean to sa# that a program does not need to chec* for D,ad filesD, or files which do not contain the data the# are alleged to contain.

1n the other hand, a programmer is at li,ert# to assume that an# file which does not contain correctl# formatted data is ?ust nonsense- heEshe does not have to tr# to ma*e sense of it with a function li*e s6ipgar%(), the program could simpl# return an error message li*e D+56 2.LED or whatever and recover in a sensi,le wa#. .t would pro,a,l# not ma*e sense to use a function li*e s6ipgar%() for files. 2or comparison alone, s6ipfilegar%() is written ,elow.
s6ipfilegar%(fp) L EB *fp; 0 while (getc(fp) I= "2n") 0 A A

/ingle !haracter I:+


There are commonl# four functionsEmacros which perform single character inputEoutput to or from files. The# are analogous to the functionsEmacros
getchar() putchar()

for the standard .E1 files and the# are calledgetc() ungetc(); putc() fgetc() fputc() getc()

and fgetc()

The difference ,etween getc() and fgetc() will depend upon a particular s#stem. .t might ,e that getcBC is implemented as a macro, whereas fgetc() is implemented as a function or vice versa. 1ne of these alternatives ma# not ,e present at all in a li,rar#. Chec* the manual, to ,e sure: +oth getc() and fgetc() fetch a single character from a fileL EB *fp; char ch; )* open file *) ch = getc (fp); ch = fgetc (fp);

These functions return a character from the specified file if the# operated successfull#, otherwise the# return BGL to indicate the end of a file or some other error. 5part from this, these functionsEmacros are 8uite unremar*a,le.
ungetc()

is a function which Iun;gets9 a character from a file. That is, it reverses the effect of the last get operation. This is not li*e writing to a file, ,ut it is li*e stepping ,ac* one position within the file. The purpose of this function is to leave the input in the correct place for other functions in a program when other functions go too far in a file. 5n example of this would ,e a program which loo*s for a word in a text file and processes that word in some wa#.
ungetc() while (getc(fp) I= " ") 0 A

The program would s*ip over spaces until it found a character and then it would *now that this was the start of a word. 7owever, having used getc() to read the first character of that word, the position in the file would ,e the second character in the word: This means that, if another function wanted to read that word from the ,eginning, the position in the file would not ,e correct, ,ecause the first character would alread# have ,een read. The solution is to use ungetc() to move the file position ,ac* a characterint returncode; returncode = ungetc(fp);

The returncode is E12 if the operation was unsuccessful.


putc()

and fputc()

These two functions write a single character to the output file, pointed to ,# fp. 5s with getc(), one of these ma# ,e a macro. The form of these statements isL EB *fp; char ch; int returncode; returncode = fputc (ch(fp); returncode = putc (ch(fp);

The returncode is the ascii code of the character sent, if the operation was successful, otherwise it is E12.
fgets()

and fputs()

Yust as gets() and puts() fetched and sent strings to standard inputEoutput files stdin and stdout, so fgets() and fputs() send strings to generaliAed files. The form of an fgets() statement is as followschar *str%uff(*return4al; int n; L EB *fp; return4al = fgets (str%uff(n(fp);

is a pointer to an input ,uffer for the string@ fp is a pointer to an open file. returnval is a pointer to a string- if there was an error in fgets() this pointer is set to the value NUEE, otherwise it is set to the value of Dstr,uffD. No more than Bn;%C characters are read ,# fgets() so the programmer has to ,e sure to set n e8ual to the siAe of the string ,uffer. B1ne ,#te is reserved for the NULL terminator.C The form of an fputs() statement is as followsstr%uff char *str; int return4al; L EB *fp; return4al = fputs (str(fp);

<here str is the NUEE terminated string which is to ,e sent to the file pointed to ,# fp. return4al is set to BGL if there was an error in writing to the file.

feof<=
This function returns a true or false result. .t tests whether or not the end of a file has ,een reached and if it has it returns Itrue9 Bwhich has an# value except AeroC@ otherwise the function returns Ifalse9 Bwhich has the value AeroC. The form of a statement using this function isL EB *fp; int outcome; outcome = feof(fp);

)ost often feof() will ,e used inside loops or conditional statements. 2or exampleconsider a loop which reads characters from an open file, pointed to ,# fp. 5 call to feof() is re8uired in order to chec* for the end of the file.
while (Ifeof(fp)) 0 ch = getc(fp); A

Translated into pidgin English, this code reads- Iwhile N1T end of file, ch e8uals get character from file9. .n ,etterBFC English the loop continues to fetch characters as long as the end of the file has not ,een reached. Notice the logical N1T operator I which stands ,efore feof().

Printer +ut$ut
5n# serious application program will have to ,e in full control of the output of a program. 2or instance, it ma# need to redirect output to the printer so that data can ,e made into hard copies. To do this, one of three things must ,e underta*enZ
stdout

must ,e redirected so that it sends data to the printer device.

Z 5 new Dstandard fileD must ,e used Bnot all C compilers use this method.C Z 5 new file must ,e opened in order to write to the printer device The first method is not generall# satisfactor# for applications programs, ,ecause the standard files stdin and stdout can onl# easil# ,e redirected from the operating s#stem command line interpreter Bwhen a program is run ,# t#ping its nameC. Examples of this aretype file / ,RN

which send a text file to the printer device. The second method is reserved for onl# a few implementations of C in which another Istandard file9 is opened ,# the local operating s#stem and is availa,le for sending data to the printer stream. This file might ,e called DstdprnD or Dstandard printer fileD and data could ,e written to the printer ,# switching writing to the file li*e thisfprintf (stdprn(&string 'd...&( integer);

The final method of writing to the printer is to open a file to the printer, personall#. To do this, a program has to give the DfilenameD of the printer device. This could ,e something li*e DP/T-D or DP/ND or DLP/TD or whatever. The filename Bactuall# called a pseudo device nameC is used to open a file in precisel# the same wa# as an# other file is opened,# using a call to fopen(). fopen() then returns a pointer to file Bwhich is effectivel# DstdprnDC and this is used to write data to a computer9s printer driver. The program code to do this should loo* something li*e the followingL EB *stdprn; if ((stdprn = fopen(&,R3:&(&w&)) == NUEE) 0 printf (&,rinter %usy or disconnected2n&); errorKhandler; A

%*a#$le
7ere is an example program which reads a source file Bfor a program, written in C, Pascal or whatever...C and lists it, along with its line num,ers. This *ind of program is useful for de,ugging programs. The program provides the user with the option of sending the output to the printer. The printer device is assumed to have the filename DP/T-D. 6etails of how to convert the program for other s#stems is given at the end.
)***************************************************************) )* *) )* E +3 : program file utility *) )* *) )***************************************************************) )* Eist a source file with line num%ers attached. Ei6e *) )* 3\,B only with lines num%ers too. *) -include .stdio.h/ -define -define -define -define -define -define DG<B + FB GN GLL 3RUB L1E+B @ $88 # @ # @ )* where output goes to *)

L EB *fin; L EB *fout = stdout;

)***************************************************************) )* Ee4el @ *) )***************************************************************) main () 0 char str%uffXsiNeY(*filename(); int ,on = false; int line = #; printf (&+ource ,rogram Eister S#.@2n2n&); if ((fin = fopen(filename()(&r&)) == NUEE) 0 printf (&2nLile not found2n&); exit (DG<B); A printf (&Gutput to printerV \)N&); if (yes()) 0 ,on = ,rinter(GN); A while (Ifeof(fin)) 0

if (fgets(str%uff(siNe(fin) I= str%uff) 0 if (Ifeof(fin)) 0 printf (&+ource file corrupted2n&); exit (DG<B); A A fprintf (fout(&'7d 's&(linePP(str%uff); A DloseLiles(,on); A )*************************************************************) )* Ee4el # *) )*************************************************************) DloseLiles(,on) int ,on; 0 if (,on) 0 ,rinter(GLL); A if (fclose(fin) I= @) 0 printf (&Brror closing input file2n&); A A )***********************************************************) ,rinter (status) int status; 0 switch (status) 0 case on: while ((fout = fopen(&,R3:&(&w&)) == NUEE) 0 printf (&,rinter %usy or disconnected2n&); printf (&2n2nRetryV \)N2n&); if (Iyes()) 0 exit(DG<B); A A %rea6; case off: while (fclose(fout) I= @) 0 printf (&?aiting to close printer stream2r&); )* switch printer file *) )* close M tidy *)

A A

)***********************************************************) )* 3ool6it *) )***********************************************************) char *filename() )* return filename *)

0 static char *filenm = &........................&; do 0 printf (&Bnter filename :&); scanf (&'$7s&(filenm); s6ipgar%(); A while (strlen(filenm) == @); return (filenm); A )*************************************************************) yes () 0 char ch; while (3RUB) 0 ch = getchar(); s6ipgar%(); switch (ch) 0 case "y" : case "\" : return (3RUB); case "n" : case "N" : return (L1E+B); A A A )*************************************************************) s6ipgar%() 0 while (getchar() I= "2n") 0 A A )* end *) )* s6ip gar%age corrupting input *) )* Ret a yes)no response from the user *)

+ut$ut

7ere is a sample portion of the output of this program as applied to one of the example programs in section G!.
# $ 5 7 8 : ; = > #@ ## #$ #5 #7 #8 #: )********************************************************) )* *) )* D programming utility : 4aria%le referencer *) )* *) )********************************************************) )* +ee section 5@ *) -include .stdio.h/ -include .ctype.h/ -define -define -define -define -define 3RUB # L1E+B @ <UJJ\ @ J1C+3R 8#$ J1C <+ FB 5$

&&& and more of the same&

!onverting the e*a#$le


The example program could ,e altered to wor* with a standard printer file DstdprnD ,# changing the following function.
,rinter (status) int status; 0 switch (status) 0 case on: fout = stdprn; %rea6; case off: A A fout = stdout; )* switch printer file *)

-iling %rrors
The standard li,rar# provides an error functionEmacro which returns a trueEfalse result according to whether or not the last filing function call returned an error condition. This is called ferror(). To chec* for an error in an open file, pointed to ,# fpL EB *fp; if (ferror(fp))

0 errorKhandler(); A

This functionEmacro does not shed an# light upon the cause of errors, onl# whether errors have occurred at all. 5 detailed diagnosis of what went wrong is onl# generall# possi,le ,# means of a deeper level call to the dis* operating s#stem B614C.

+ther -acilities for High Level -iles


2iles which have ,een opened ,# fopen() can also ,e handled with the following additional functionsfread() fwrite() ftell() fsee6() rewind() fflush()

These functions provide facilities to read and write whole ,loc*s of characters in one operation as well as further facilities to locate and alter the current focus of attention within a file. The# offer, essentiall#, low level filing operations for files which have ,een opened for high level use:
fread()

and fwrite()

These functions read and write whole ,loc*s of characters at a time. The form of fread() is as followsL EB *fp; int noread(n(siNe; char *ptr; noread = fread (ptr(siNe(n(fp);

The parameters in parentheses provide information a,out where the data will ,e stored once the# have ,een read from a file. fp is a pointer to an open file@ ptr is a pointer to the start of a ,loc* of memor# which is to store the data when it is read@ siAe is the siAe of a ,loc* of data in characters@ n is the num,er of ,loc*s of data to ,e read. 2inall# noread is a return value which indicates the num,er of ,loc*s which was actuall# read during the operation. .t is important to chec* that the num,er of ,loc*s expected is the same as the num,er received ,ecause something could have gone wrong with the reading process. BThe dis* might ,e corrupted or the file might have ,een altered in some wa#.C fwrite() has an identical call structure to fread()L EB *fp; int nowritten(n(siNe;

char *ptr; nowritten = fread (ptr(siNe(n(fp);

This time the parameters in parentheses provide information a,out where the data, to ,e written to a file, will ,e found. fp is a pointer to an open file@ ptr is a pointer to the start of a ,loc* of memor# at which the data are stored@ siAe is the siAe of a D,loc*D of data in characters@ n is the num,er of ,loc*s of data to ,e read@ nowritten is a return value which indicates the actual num,er of ,loc*s which was written. 5gain, this should ,e chec*ed. 5 caution a,out these functions- each of these ,loc* transfer routines ma*es an important assumption a,out the wa# in which data are stored in the computer s#stem. .t is assumed that the data are stored contiguously in the memor#, that is, side ,# side, in se8uential memor# locations. .n some s#stems this can ,e difficult to arrange Bin multi;tas*ing s#stems in particularC and almost impossi,le to guarantee. )emor# which is allocated in C programs ,# the function malloc() does not guarantee to find contiguous portions of memor# on successive calls. This should ,e noted carefull# when developing programs which use these calls.

-ile Positions4 ftell<= and fseek<=


tells a program its position within a file, opened ,# fopen(). fsee6() see*s a specified place within a file, opened ,# fopen(). Normall# high level readEwrite functions perform as much management over positions inside files as the programmer wants, ,ut in the event of their ,eing insufficient, these two routines can ,e used. The form of the function calls isftell() long int pos; L EB *fp; pos = ftell(fp);

is an open file, which is in some state of ,eing read or written to. pos is a long integer value which descri,es the position in terms of the num,er of characters from the ,eginning of the file. 5ligning a file portal with a particular place in a file is more sophisticated than simpl# ta*ing note of the current position. The call to fsee6() loo*s li*e thisfp long int pos; int mode(returncode; L EB *fp;

returncode = fsee6 (fp(pos(mode);

The parameters have the following meanings. fp is a pointer to a file opened ,# fopen(). pos is some wa# of descri,ing the position re8uired within a file. mode is an integer which specifies the wa# in which pos is to ,e interpreted. 2inall#, returncode is an integer whose value is ! if the operation was successful and ;% if there was an error.

@ # $ pos is an offset measured relative to the end of the file. 4ome examples help to show how this wor*s in practicelong int pos = 8@; int mode = @(returncode; L EB *fp; pos pos

is an offset measured relative to the ,eginning of the file. is an offset measured relative to the current position.

if (fsee6 (fp(pos(mode) I= @) )* find 8@th character *) 0 printf(&BrrorI2n&); A fsee6(fp(@E(@); fsee6(fp($E(@); if (fsee6 (fp(#@E(#) I= @) 0 printf(&BrrorI2n&); A )* find %eginning of file *) )* find the end of a file *) )* mo4e #@ char"s forward *)

The E9s indicate long constants.


rewind()

is a macro, ,ased upon fsee6(), which resets a file position to the ,eginning of the file. e.g.
rewind() L EB *fp; rewind(fp); fsee6(fp(@E(@); )* = rewind() *)

fflush()

This is a macroEfunction which can ,e used on files which have ,een opened for writing or appending. .t flushes the output ,uffer which means that it forces the characters in the output ,uffer to ,e written to the file. .f used on files which are open for reading, it causes the input ,uffer to ,e emptied Bassuming that this is allowed at allC. ExampleL EB *fp; fflush(fp);

Low Level -iling +$erations


Normall# a programmer can get awa# with using the high level inputEoutput functions, ,ut there ma# ,e times when C9s predilection for handling all high level inputEoutput as

text files, ,ecomes a nuisance. 5 program can then use a set of low level .E1 functions which are provided ,# the standard li,rar#. These areopen() close() creat() read() write() rename() unlin6())remo4e() lsee6()

These low level routines wor* on the operating s#stem9s end of the file portals. The# should ,e regarded as ,eing advanced features of the language ,ecause the# are dangerous routines for ,ug ridden programs. The data which the# deal with is untranslated- that is, no conversion from characters to floating point or integers or an# t#pe at all ta*e place. 6ata are treated as a raw stream of ,#tes. Low level functions should not ,e used on an# file at the same time as high level routines, since high level file handling functions often ma*e calls to the low level functions. <or*ing at the low level, programs can create, delete and rename files ,ut the# are restricted to the reading and writing of untranslated data- there are no functions such as fprintf() or fscanf() which ma*e t#pe conversions. 5s well as the functions listed a,ove a local operating s#stem will dou,tless provide special function calls which ena,le a programmer to ma*e the most of the facilities offered ,# the particular operating environment. These will ,e documented, either in a compiler manual, or in an operating s#stem manual, depending upon the s#stem concerned. BThe# might concern special graphics facilities or windowing s#stems or provide wa#s of writing special s#stem dependent data to dis* files, such as dateEtime stamps etc.C

-ile descri$tors
5t the low level, files are not handled using file pointers, ,ut with integers *nown as file handles or file descriptors. 5 file handle is essentiall# the num,er of a particular file portal in an arra#. .n other words, for all the different terminolog#, the# descri,e the same thing. 2or exampleint fd;

would declare a file handle or descriptor or portal or whatever it is to ,e called.


open() open()

is the low level file open function. The form of this function call is-

int fd( mode; char *filename; fd = open (filename(mode);

where filename is a string which holds the name of the file concerned, mode is a value which specifies what the file is to ,e opened for and fd is either a num,er used to distinguish the file from others, or ;% if an error occurred. 5 program can give more information to this function than it can to fopen() in order to define exactl# what open() will do. The integer $ode is a message or a pseudo register which passes the necessar# information to open(), ,# using the following flagsGKR<GNE\ GK?RGNE\ GKR<?R Read access only ?rite access only Read)?rite access

and on some compilersGKDRB13 GK3RUND GK1,,BN< GKBCDE Dreate the file if it does not exist 3runcate the file if it does exist Lind the end of the file %efore each write Bxclude. Lorce create to fail if the file exists.

The macro definitions of these flags will ,e included in a li,rar# file- find out which one and -include it in the program. The normal procedure is to open a file using one of the first three modes. 2or example-define L1 EB< -# main() 0 char *filename(); int fd; fd = open(filename()( GKR<GNE\); if (fd == L1 EB<) 0 printf (&Lile not found2n&); errorKhandler (failed); A A

This opens up a read;onl# file for low level handling, with error chec*ing. 4ome s#stems allow a more flexi,le wa# of opening files. The four appended modes are values which can ,e ,itwise 1/ed with one of the first three in order to get more mileage out of open(). The ,itwise 1/ operator is the vertical ,ar DUD. 2or example, to emulate the fopen() function a program could opt to create a file if it did not alread# existfd = open (filename()( GKR<GNE\ Q GKDRB13);

open()

sets the file position to Aero if the file is opened successfull#.

close()

releases a file portal for use ,# other files and ,rings a file completel# up to date with regard to an# changes that have ,een made to it. Li*e all other filing functions, it returns the value ! if it performs successfull# and the value ;% if it fails. e.g.
close() -define L1 EB< -# if (close(fd) == L1 EB<) 0 printf (&BRRGRI&); A

creat()

This function creates a new file and prepares it for access using the low level file handling functions. .f a file which alread# exists is created, its contents are discarded. The form of this function call isint fd( pmode; char *filename; fd = creat(filename(pmode);

must ,e a valid filename@ pmode is a flag which contains access;privilege mode ,its Bs#stem specific information a,out allowed accessC and fd is a returned file handle. .n the a,sence of an# information a,out pmode, this parameter can ,e set to Aero. Note that, the action of creating a file opens it too. Thus after a call to creat, #ou should close the file descriptor.
filename

read<=
This function gets a ,loc* of information from a file. The data are loaded directl# into memor#, as a se8uence of ,#tes. The user must provide a place for them Beither ,# ma*ing an arra# or ,# using malloc() to reserve spaceC. read() *eeps trac* of file positions automaticall#, so it actuall# reads the next ,loc* of ,#tes from the current file position. The following example reads n ,#tes from a fileint return4alue( fd( n; char *%uffer; if ((%uffer = malloc(siNe)) == NUEE) 0 puts (&Gut of memory2n&); errorKhandler (); A return4alue = read (fd(%uffer(n);

The return value should ,e chec*ed. .ts values are defined as follows-

@ -# n

End of file Error occurred the num,er of ,#tes actuall# read. B.f all went well this should ,e e8ual to n.C

write()

This function is the opposite of read(). .t writes a ,loc* of n ,#tes from a contiguous portion of memor# to a file which was opened ,# open(). The form of this function isint return4alue( fd( n; char *%uffer; return4alue = write (fd(%uffer(n);

The return value should, again, ,e chec*ed for errors-#

Error
n

Num,er of ,#tes written


lsee%()

Low level file handing functions have their e8uivalent of fsee6() for finding a specific position within a file. This is almost identical to fsee6() except that it uses the file handle rather than a file pointer as a parameter and has a different return value. The constants should ,e declared long int, or simpl# long.
-define L1 EB< -#E

long int pos(offset(fd; int mode(returncode; if ((pos = fsee6 (fd(offset(mode)) == L1 EB<) 0 printf(&BrrorI2n&); A

gives the new file position if successful, and ;% BlongC if an attempt was made to read past the end of the file. The values which mode can ta*e arepos @ # $

1ffset measured relative to the ,eginning of the file. 1ffset measured relative to the current position. 1ffset measured relative to the end of the file.

unlin%()

and remo

e()

These functions delete a file from dis* storage. 1nce deleted, files are usuall# irretrieva,le. The# return ;% if the action failed.
-define L1 EB< -# int return4alue; char *filename; if (unlin6 (filename) == L1 EB<) 0 printf (&Dan"t delete 's2n&(filename); A if (remo4e (filename) == L1 EB<) 0 printf (&Dan"t delete 's2n&(filename); A

is a string containing the name of the file concerned. This function can fail if a file concerned is protected or if it is not found or if it is a device. B.t is impossi,le to delete the printer:C
filename

renameBC This function renames a file. The programmer specifies two filenames- the old filename and a new file name. 5s usual, it returns the value ;% if the action fails. 5n example illustrates the form of the rename() call-define L1 EB< -# char *old(*new; if (rename(old(new) == L1 EB<) 0 printf (&Dan"t rename 's as 's2n&(old(new); A

can fail ,ecause a file is protected or ,ecause it is in use, or ,ecause one of the filenames given was not valid.
rename()

%*a#$le
This example strings together some low level filing actions so as to illustrate their use in a real program. The idea is to present a *ind of file or Dpro?ectD menu for creating, deleting, renaming files. 5 rather fee,le text editor allows the user to enter "HH characters of text which can ,e saved.
)***************************************************************)

)* *) )* EG? EBSBE L EB H1N<E NR *) )* *) )***************************************************************) -include .stdio.h/ -include .ctype.h/ -include .fcntl.h/ -define -define -define -define -define -define DG<B + FB LNJ+ FB 3RUB L1E+B L1 EB< @ $88 5@ # @ -#

)* defines GKR<GNE\ etc.. *)

)* Jax siNe of filenames *)

-define DER+DRN() putchar("2f") -define NB?E NB() putchar("2n") int fd; )***************************************************************) )* Ee4el @ *) )***************************************************************) main () 0 char *data(get6ey()(*malloc(); if ((data = malloc(+ FB)) == NUEE) 0 puts (&Gut of memory2n&); return (DG<B); A while (3RUB) 0 menu(); switch (get6ey()) 0 case "l" : EoadLile(data); %rea6; case "s" : +a4eLile(data); %rea6; case "e" : Bdit(data); %rea6; case "d" : <eleteLile(); %rea6; case "r" : RenameLile(); %rea6; case "O" : if (sure()) 0 return (DG<B); A %rea6; A A A

)*************************************************************) )* Ee4el # *) )*************************************************************) menu () 0 DER+DRN(); printf (& ---------------------------------2n&); printf (&Q JBNU Q2n&); printf (&Q [[[[[[ Q2n&); printf (&Q Q2n&); printf (&Q E) Eoad Lile Q2n&); printf (&Q +) +a4e Lile Q2n&); printf (&Q B) Bdit Lile Q2n&); printf (&Q <) <elete Lile Q2n&); printf (&Q R) Rename Lile Q2n&); printf (&Q ]) ]uit Q2n&); printf (&Q Q2n&); printf (&Q +elect Gption and RB3URN Q2n&); printf (&Q Q2n&); printf (& --------------------------------- 2n&); NB?E NB(); A )*************************************************************) EoadLile(data) char *data; 0 char *filename()(get6ey(); int error; fd = open(filename()( GKR<GNE\); if (fd == L1 EB<) 0 printf (&Lile not found2n&); return (L1 EB<); A error = read (fd(data(+ FB); if (error == L1 EB<) 0 printf (&Brror loading file2n&); wait(); A else 0 if (error I= + FB) 0 printf (&Lile was corrupted2n&); wait(); A A close (fd(data(+ FB); )* Eow le4el load *)

return (error); A )*************************************************************) +a4eLile(data) char *data; 0 char *filename()(get6ey()(*fname; int error(fd; fd = open ((fname = filename())( GK?RGNE\); if (fd == L1 EB<) 0 printf (&Lile cannot %e written to2n&); printf (&3ry to create new fileV \)N2n&); if (yes()) 0 if ((fd = DreateLile(fname)) == L1 EB<) 0 printf (&Dannot create file 's2n&(fname); return (L1 EB<); A A else 0 return (L1 EB<); A A error = write (fd(data(+ FB); if (error . + FB) 0 printf (&Brror writing to file2n&); if (error I= L1 EB<) 0 printf (&Lile only partially written2n&); A A close (fd(data(+ FB); wait(); return (error); A )*************************************************************) Bdit(data) char *data; 0 char *ptr; int ctr = @; printf (&Dontents of file:2n2n&); )* primiti4e text editor *) )* Eow Ee4el sa4e *)

for (ptr = data; ptr . (data P + FB); ptrPP) 0 if (isprint(*ptr)) 0 putchar(*ptr); if ((ctrPP ' :@) == @) 0 NB?E NB(); A A A printf (&2n2nBnter '#d characters:2n&(+ FB); for (ptr = data; ptr . (data P + FB); ptrPP) 0 *ptr = getchar(); A s6ipgar%(); A )*************************************************************) <eleteLile() )* <elete a file from current dir *)

0 char *filename()(get6ey()(*fname; printf (&<elete Lile2n2n&); fname = filename(); if (sure()) 0 if (remo4e(fname) == L1 EB<) 0 printf (&Dan"t delete 's2n&(fname); A A else 0 printf (&Lile NG3 deletedI2n&); A wait(); A )*************************************************************) RenameLile() 0 char oldXLNJ+ FBY(*new; printf (&Rename from GE< to NB?2n2nGE<: &); strcpy (old(filename()); printf (&2nNB?: &); new = filename(); if (rename(old(new) == L1 EB<) 0

printf (&Dan"t rename 's as 's2n&(old(new); A wait(); A )*************************************************************) )* Ee4el $ *) )*************************************************************) DreateLile (fname) char *fname; 0 int fd; if ((fd = creat(fname(@)) == L1 EB<) 0 printf (&Dan"t create file 's2n&(fname); return (L1 EB<); A return (fd); A )*************************************************************) )* 3ool6it *) )*************************************************************) char *filename() 0 static char statfilenmXLNJ+ FBY; do 0 printf (&Bnter filename :&); scanf (&'$7s&(statfilenm); s6ipgar%(); A while (strlen(statfilenm) == @); return (statfilenm); A )**************************************************************) sure () )* is the user sure V *) )* return filename *)

0 printf (&1re you a%solutely( unOuestiona%ly certainV \)N2n&); return(yes()); A )**************************************************************) yes() 0 char get6ey(); while (3RUB)

0 switch(get6ey()) 0 case "y" : return (3RUB); case "n" : return (L1E+B); A A

)**************************************************************) wait() 0 char get6ey(); printf (&,ress a 6ey2n&); get6ey(); A )**************************************************************) char get6ey() 0 char ch; ch = getchar(); s6ipgar%(); return((char)tolower(ch)); A )**************************************************************) s6ipgar%() 0 while (getchar() I= "2n") 0 A A )* end *) )* s6ip gar%age corrupting input *) )* single 6ey P RB3URN response *)

(uestions
%. <hat are the followingF %. 2ile name ". 2ile pointer G. 2ile handle ". <hat is the difference ,etween high and low level filingF G. <rite a statement which opens a high level file for reading. . <rite a statement which opens a low level file for writing. H. <rite a program which chec*s for illegal characters in text files. 3alid characters are 54C.. codes %!,%G,and G"..%"M. 5n#thing else is illegal for programs. M. <hat statement performs formatted writing to text filesF

(. Print out all the header files on #our s#stem so that #ou can see what is defined where:

/tructures and &nions


/rouping data. Tidying up progra$s. Tid# programs are a ,lessing to programmers. Tid# data are ?ust as important. 5s programs ,ecome increasingl# complex, their data also grow in complexit# and single, independent varia,les or arra#s are no longer enough. <hat one then needs is a data structure. This is where a new t#pe of varia,le comes in- it is called a struct t#pe, or in other languages, a record. struct t#pes or structures are usuall# lumped together with another t#pe of varia,le called a union. .n fact their purposes are 8uite different.

+lac* +ox 6atastruct6eclarations again4cope againUsing 4tructures5rra#s of 4tructuresExample G'4tructures of 4tructuresPointers to 4tructuresExample G&Pre;initialiAing 4tatic 4tructuresCreating )emor# for 6#namical struct T#pesUnions>uestions "M-

+rgani2ation4 Black Bo* 'ata


<hat is the relationship ,etween a program and its dataF Thin* of a program as an operator which operates on the memor# of the computer. Local data are operated upon inside sealed function capsules, where the# are protected from the reach of certain parts of a program. Glo,al data are wide open to alteration ,# an# part of a program. .f a program were visualiAed schematicall# what would it loo* li*eF 5 traditional flow diagramF No- a computer program onl# loo*s li*e a flow diagram at the machine code level and that is too primitive for C programmers. 1ne wa# of visualiAing a program is

illustrated ,# the diagram over the page.

This shows a program as a *ind of societ# of sealed function capsules which wor* together li*e a ,eehive of activit# upon a hone#com, of program data. This imaginative idea is not a ,ad picture of a computer program, ,ut it is not complete either. 5 program has to manipulate data- it has to loo* at them, move them around and cop# them from place to place. 5ll of these things would ,e ver# difficult if data were scattered a,out li,erall#, with no particular structure. 2or this reason C has the facilit#, within it, to ma*e sealed capsules ; not of program code ; ,ut of program data, so that all of these actions ver# simpl# ,# grouping varia,les together in convenient pac*ages for handling. These capsules are called structures.

struct
5 structure is a pac*age of one or usuall# more varia,les which are grouped under a single name. 4tructures are not li*e arra#s- a structure can hold an# mixture of different t#pes of data- it can even hold arra#s of different t#pes. 5 structure can ,e as simple or as complex as the programmer desires. The word struct is a reserved word in C and it represents a new data t#pe, called an aggregate t#pe. .t is not an# single t#pe- the purpose of structures is to offer a tool for ma*ing whatever shape or form of varia,le pac*age that a programmer wishes. 5n# particular structure t#pe is given a name, called a structure;name and the varia,les Bcalled mem,ersC within a structure t#pe are also given names. 2inall#, ever# varia,le which is declared to ,e a particular structure t#pe has a name of its own too. This plethora of names is not reall# as complicated as it sounds.

'eclarations
5 structure is declared ,# ma*ing a ,lan* template for a varia,le pac*age. This is most easil# seen with the help of an example. The following statement is actuall# a declaration, so it ,elongs with other declarations, either at the head of a program or at the start of a ,loc*.
struct ,ersonal<ata 0 char nameXnamesiNeY; char addressXaddresssiNeY; int \earGf9irth; int JonthGf9irth; int <ayGf9irth; A;

This purpose of this statement is to create a model or template to define what a varia,le of t#pe struct ,ersonal<ata will loo* li*e. .t sa#s- define a t#pe of varia,le which collectivel# holds a string called name, a string called address and three integers called \earGf9irth, JonthGf9irth and <ayGf9irth. 5n# varia,le which is declared to ,e of t#pe struct ,ersonal<ata will ,e collectivel# made up of parts li*e these. The list of varia,le components which ma*e up the structure are called the mem,ers of the structurethe names of the mem,ers are not the names of varia,les, ,ut are a wa# of naming the parts which ma*e up a structure varia,le. BNote- a varia,le which has ,een declared to ,e of t#pe struct so$ething is usuall# called ?ust a structure rather than a structure varia,le. The distinction is maintained here in places where confusion might arise.C The names of mem,ers are held separate from the names of other identifiers in C, so it is 8uite possi,le to have varia,le names and struct mem,er names which are the same. 1lder compilers did not support this luxur#. 5t this stage, no storage has ,een given over to a varia,le, nor has an# varia,le ,een declared- onl# a t#pe has ,een defined. 7aving defined this t#pe of structure, however, the programmer can declare varia,les to ,e of this t#pe. 2or examplestruct ,ersonal<ata x;

declares a varia,le called x to ,e of t#pe struct ,ersonal<ata. x is certainl# not a ver# good name for an# varia,le which holds a person9s personal data, ,ut it contrasts well with all the other names which are a,ound and so it serves its purpose for now. +efore moving on to consider how structures can ,e used, it is worth pausing to show the different wa#s in which structures can ,e declared. The method shown a,ove is pro,a,l# the most common one, however there are two e8uivalent methods of doing the same thing. 5 varia,le can ,e declared immediatel# after the template definition.
struct ,ersonal<ata

0 char nameXnamesiNeY; char addressXaddresssiNeY; int \earGf9irth; int JonthGf9irth; int <ayGf9irth; A x; )* 4aria%le identifier follows type *)

5lternativel#, typedef can ,e used to cut down a ,it on t#ping in the long term. This t#pe definition is made once at the head of the program and then su,se8uent declarations are made ,# using the new nametypedef struct 0 char nameXnamesiNeY; char addressXaddresssiNeY; int \earGf9irth; int JonthGf9irth; int <ayGf9irth; A ,ersonal<ata;

then declare,ersonal<ata x;

5n# one of these methods will do.

/co$e
+oth structure t#pes and structure varia,les o,e# the rules of scope- that is to sa#, a structure t#pe declaration can ,e local or glo,al, depending upon where the declaration is made. 4imilarl# if a structure t#pe varia,le is declared locall# it is onl# valid inside the ,loc* parentheses in which it was defined.
main () 0 struct GNB 0 int a; float %; A; struct GNB x; A

function () 0 struct GNB x; A )* 3his line is illegal( since GNB *) )* is a local type definition *) )* <efined only in main() *)

&sing /tructures
7ow does a program use the varia,les which are loc*ed inside structuresF The whole point a,out structures is that the# can ,e used to group data into sensi,le pac*ages which can then ,e treated as single o,?ects. Earl# C compilers, some of which still exist toda#, placed ver# severe restrictions upon what a program could do with structures. Essentiall#, the mem,ers of a structure could ,e assigned values and pointers to individual structures could ,e found. 5lthough this sounds highl# restrictive, it did account for the most fre8uent uses of structures. )odern compilers allow more flexi,le use of structuresprograms can assign one structure varia,le to another structure varia,le Bprovided the structures match in t#peC@ structure varia,les can ,e passed, whole, as parameters to functions and functions can return structure values. This ma*es structures extremel# powerful data o,?ects to have in a program. 5 structure is assigned to another structure ,# the following statements.
struct ,ersonal x(y; x = y;

The whole ,undle of mem,ers is copied in one statement: 4tructures are passed as parameters in the usual wa#function (x(y);

The function then has to ,e declaredfunction (x(y) struct ,ersonal<ata x(y; 0 A

2inall#, a function which returns a structure varia,le such as0 struct ,ersonal<ata x(function(); x = function(); A

would ,e declared in the following wa#-

struct ,ersonal<ata function () 0 A

Notice that the return t#pe of such a function must also ,e declared in the function which calls that it, in the usual wa#. The reader will ,egin to see that structure names account for a good deal of t#ping: The t#pedef statement is a ver# good wa# of reducing this ,urden. The mem,ers of a structure are accessed with the . dot character. This is a structure $e$ber operator. Consider the structure varia,le x, which has the t#pe struct ,ersonal<ata. The mem,ers of x could ,e assigned ,# the following programmain () 0 struct ,ersonal<ata x; Lill1rray (&+ome name&( x.name); Lill1rray (&+ome address&( x.address); x.\earGf9irth = #>=;; x.JonthGf9irth = $; x.<ayGf9irth = #>; A

where Lill1rray() is a h#pothetical function which copies the string in the first parameter to the arra# in the second parameter. The dot ,etween the varia,le and the names which follow implies that the statements in this ,rief program are tal*ing a,out the mem,ers in the structure varia,le x, rather than the whole collective ,undle. )em,ers of actual structure varia,les are alwa#s accessed with this dot operator. The general form of a mem,er reference isstructure variable.member name

This applies to an# t#pe of structure varia,le, including those accessed ,# pointers. <henever a program needs to access the mem,ers of a structure, this dot operator can ,e used. C provides a special mem,er operator for pointers, however, ,ecause the# are used so often in connection with structures. This new operator is descri,ed ,elow.

3rra,s of /tructures
Yust as arra#s of an# ,asic t#pe of varia,le are allowed, so are arra#s of a given t#pe of structure. 5lthough a structure contains man# different t#pes, the compiler never gets to *now this information ,ecause it is hidden awa# inside a sealed structure capsule, so it can ,elieve that all the elements in the arra# have the same t#pe, even though that t#pe is itself made up of lots of different t#pes. 5n arra# would ,e declared in the usual wa#int i;

struct ,ersonal<ata x(arrayXsiNeY;

The mem,ers of the arra#s would then ,e accessed ,# statements li*e the following examplesarrayXiY = x; arrayXiY = arrayXUY; arrayXiY.\earGf9irth = #>=;; i = arrayX$Y.JonthGf9irth;

%*a#$le
This listing uses a structure t#pe which is slightl# different to Personal6ata in that string pointers are used instead of arra#s. This allows more convenient handling of real;life strings.
)*********************************************************) )* *) )* +tructures <emo *) )* *) )*********************************************************) )* +imple program to initialiNe some structures *) )* and to print them out again. <oes no error *) )* chec6ing( so %e wary of string siNes etc.. *) -include .stdio.h/ -define -define -define -define N1JB+ FB 1<<R+ FB NGGL,BR+GN+ NB?E NB() 5@ =@ $@ putchar("2n");

)*********************************************************) typedef struct 0 char *Name; char *1ddress; int \earGf9irth; int JonthGf9irth; int <ayGf9irth; A ,erson<at; )*********************************************************) main () 0 ,erson<at recordXNGGL,BR+GN+Y; ,erson<at ,ersonal<etails(); )* Ja6e some records *)

int person; printf (&9irth Records Lor Bmployees&); printf (&2n---------------------------&); printf (&2n2n&); printf (&Bnter data2n&); for (person = @; person . NGGL,BR+GN+; personPP) 0 recordXpersonY = ,ersonal<etails(); NB?E NB(); A <isplayRecords (record); A )*********************************************************) ,erson<at ,ersonal<etails() )* No error chec6ingI *)

0 ,erson<at dat; char str%uffX1<<R+ FBY( *malloc(); printf (&Name :&); dat.Name = malloc(N1JB+ FB); strcpy (dat.Name(gets(str%uff)); printf (&1ddress :&); dat.1ddress = malloc(1<<R+ FB); strcpy (dat.1ddress(gets(str%uff)); printf (&\ear of %irth:&); dat.\earGf9irth = getint (#>@@(#>=;); printf (&Jonth of %irth:&); dat.JonthGf9irth = getint (#(#$); printf (&<ay of %irth:&); dat.<ayGf9irth = getint(#(5#); return (dat); A )**********************************************************) <isplayRecords (rec) ,erson<at recXNGGL,BR+GN+Y; 0 int pers; for (pers = @; pers . NGGL,BR+GN+; persPP) 0 printf (&Name : 's2n&( recXpersY.Name); printf (&1ddress : 's2n&( recXpersY.1ddress); printf(&<ate of 9irth: '#d)'#d)'#d2n&(recXpersY.<ayGf9irth( recXpersY.JonthGf9irth(recXpersY.\earGf9irth); NB?E NB();

)**********************************************************) )* 3ool6it *) )**********************************************************) getint (a(%) int a(%; 0 int p( i = a - #; )* return int %etween a and % *)

for (p=@; ((a / i) QQ (i / %)); pPP) 0 printf (&V : &); scanf (&'d&(Mi); if (p / $) 0 s6ipgar%(); p = @; A A s6ipgar%(); return (i); A )**********************************************************) s6ipgar%() )* +6ip input gar%age corrupting scanf *)

0 while (getchar() I= "2n") 0 A A )* end *)

/tructures of /tructures
4tructures are said to nest. This means that structure templates can contain other structures as mem,ers. Consider two structure t#pesstruct firstKstructure 0 int 4alue; float num%er; A;

and
struct secondKstructure 0 int tag;

struct firstKstructure fs; A x;

These two structures are of different t#pes, #et the first of the two is included in the second: 5n instance of the second structure would ,e initialiAed ,# the following assignments. The structure varia,le name is xx.tag = #@; x.fs.4alue = $@; x.fs.num%er = 5@.@;

Notice the wa# in which the mem,er operator . can ,e used over and over again. Notice also that no parentheses are necessar#, ,ecause the reference which is calculated ,# this operator is wor*ed out from left to right. This nesting can, in principle, go on man# times, though some compilers might place restrictions upon this nesting level. 4tatements such as4aria%le.tag#.tag$.tag5.tag7 = something;

are pro,a,l# o*a# Bthough the# do not reflect good programmingC. 4tructures should nest safel# a few times. 5 word of caution is in order here. There is a pro,lem with the a,ove scheme that has not #et ,een addressed. .t is this- what happens if a structure contains an instance of itselfF 2or examplestruct Regression 0 int i; struct Regression tag; A

There is simpl# no wa# that this *ind of statement can ma*e sense, unless the compiler9s target computer has an infinite suppl# of memor#: /eferences to varia,les of this t#pe would go on for ever and an infinite amount of memor# would ,e needed for ever# varia,le. 2or this one reason, it is for,idden for a structure to contain an instance of itself. <hat is not for,idden, however, is for a structure to contain an instance of a pointer to its own t#pe B,ecause a pointer is not the same t#pe as a structure- it is merel# a varia,le which holds the address of a structureC. Pointers to structures are 8uite invalua,le, in fact, for ,uilding data structures such as lin*ed lists and trees. These extremel# valua,le devices are descri,ed ,elow.

Pointers to /tructures
5 pointer to a structure t#pe varia,le is declared ,# a statement li*estruct Name *ptr;

is then, formall#, a pointer to a structure of t#pe Name onl#. ptr can ,e assigned to an# other pointer of similar t#pe and it can ,e used to access the mem,ers of a structure. .t is in the second of these actions that a new structure operator is revealed. 5ccording to the rules which have descri,ed so far, a structure mem,er could ,e accessed ,# pointers with the following statementsptr struct ,ersonal<ata *ptr; (*ptr).\earGf9irth = $@;

This sa#s let the mem,er \earGf9irth of the structure pointed to ,# ptr, have the value "!. Notice that *ptr, ,# itself, means the contents of the address which is held in ptr and notice that the parentheses around this statement avoid an# confusion a,out the precedence of these operators. There is a ,etter wa# to write the a,ove statement, however, using a new operator- -/. This is an arrow made out of a minus sign and a greater than s#m,ol and it is used simpl# as followsstruct ,ersonal<ata *ptr; ptr-/\earGf9irth = $@;

This statement is identical in ever# wa# to the first version, ,ut since this *ind of access is re8uired so fre8uentl#, when dealing with structures, C provides this special operator to ma*e the operation clearer. .n the statements a,ove, it is assumed that ptr has ,een assigned to the address of some pre;assigned structure- for example, ,# means of a statement such asptr = Mx;

where x is a pre;assigned structure.

%*a#$le
)*********************************************************) )* *) )* +tructures <emo -$ *) )* *) )*********************************************************) )* 3his is the same program( using pointer references *) )* instead of straight 4aria%le references. i.e. this *) )* uses 4aria%le parameters instead of 4alue params *) -include .stdio.h/ -define N1JB+ FB 5@ -define 1<<R+ FB =@ -define NGGL,BR+GN+ $@

-define NB?E NB()

putchar("2n");

)*********************************************************) typedef struct 0 char *Name; char *1ddress; int \earGf9irth; int JonthGf9irth; int <ayGf9irth; A ,erson<at; )*********************************************************) main () 0 ,erson<at recordXNGGL,BR+GN+Y; int person; printf (&9irth Records Lor Bmployees&); printf (&2n---------------------------&); printf (&2n2n&); printf (&Bnter data2n&); for (person = @; person . NGGL,BR+GN+; personPP) 0 ,ersonal<etails(M(recordXpersonY)); NB?E NB(); A <isplayRecords (record); A )*********************************************************) ,ersonal<etails(dat) ,erson<at *dat; 0 char str%uffX1<<R+ FBY( *malloc(); printf (&Name :&); dat-/Name = malloc(N1JB+ FB); strcpy (dat-/Name(gets(str%uff)); printf (&1ddress :&); dat-/1ddress = malloc(1<<R+ FB); strcpy (dat-/1ddress(gets(str%uff)); printf (&\ear of %irth:&); dat-/\earGf9irth = getint (#>@@(#>=;); printf (&Jonth of %irth:&); dat-/JonthGf9irth = getint (#(#$); printf (&<ay of %irth:&); )* No error chec6ingI *) )* Ja6e some records *)

dat-/<ayGf9irth = getint(#(5#); A )**********************************************************) <isplayRecords (rec) ,erson<at recXNGGL,BR+GN+Y; 0 int pers; for (pers = @; pers . NGGL,BR+GN+; persPP) 0 printf (&Name : 's2n&( recXpersY.Name); printf (&1ddress : 's2n&( recXpersY.1ddress); printf(&<ate of 9irth: '#d)'#d)'#d2n&(recXpersY.<ayGf9irth( recXpersY.JonthGf9irth(recXpersY.\earGf9irth); NB?E NB(); A A )**********************************************************) )* 3ool6it *) )**********************************************************) )* 1s %efore *)

Pre>initiali2ing /tatic /tructures


.n the chapter on arra#s it was shown how static and external t#pe arra#s could ,e initialiAed with values at compile time. 4tatic and external structures can also ,e pre; assigned ,# the compiler so that programs can set up options and starting conditions in a convenient wa#. 5 static varia,le of t#pe ,erson<at Bas in the example programsC could ,e declared and initialiAed in the same statement-define N1JB+ FB $@ -define 1<<RB+++ FB $$ struct ,erson<at 0 char *name; char *address; int \earGf9irth; int JonthGf9irth; int <ayGf9irth; A; main () 0 static struct ,ersonal<ata 4aria%le = 0 &1lice ?onderment&( &+omewhere in ,aradise&( #>:8( 8( #$

A; )* rest of program *) A

The items in the curl# ,races are matched to the mem,ers of the structure varia,le and an# items which are not initialiAed ,# items in the list are filled out with Aeros.

!reating Me#or, for ',na#ical struct ",$es


Pro,a,l# the single most fre8uent use of struct t#pe varia,les is in the ,uilding of d#namical data structures. 6#namical data are data which are created explicitl# ,# a program using a scheme of memor# allocation and pointers. Normal program data, which are reserved space ,# the compiler, are, in fact, static data structures ,ecause the# do not change during the course of a program- an integer is alwa#s an integer and an arra# is alwa#s an arra#- their siAes cannot change while the program is running. 5 d#namical structure is ,uilt using the memor# allocation functionmalloc()

and pointers. The idea is to create the memor# space for a new structure as and when it is needed and to use a pointer to access the mem,ers of that structure, using the -/ operator. malloc() was descri,ed in connection with strings- it allocates a fixed num,er of ,#tes of memor# and returns a pointer to that data. 2or instance, to allocate ten ,#tes, one would write something li*e thischar *malloc()( *ptr; ptr = malloc(#@);

is then a pointer to the start of that ,loc* of %! ,#tes. <hen a program wants to create the space for a structure, it has a template for that structure, which was used to define it, ,ut it does not generall# *now, in advance, how man# ,#tes long a structure is. .n fact, it is seldom possi,le to *now this information, since a structure ma# occup# more memor# than the sum of its parts. 7ow then does a program *now how must space to allocateF The C compiler comes to the rescue here, ,# providing a compile time operator called
ptr siNeof ()

which calculates the siAe of an o,?ect while a program is compiling. 2or examplesiNeof(int) siNeof(char)

<or*s out the num,er of ,#tes occupied ,# the t#pe int.

<or*s out the num,er of ,#tes occupied ,# a single character. This e8uals %, in fact. wor*s out the num,er of ,#tes needed to store a single structure varia,le. 1,viousl# this tool is ver# useful for wor*ing with malloc(). The memor# allocation statement ,ecomes something li*esiNeof(struct ,ersonal<ata) ptr = malloc(siNeof(type name));

There is a pro,lem with this statement though- malloc() is declared as a function which returns a t#pe Ipointer to character9 whereas, here, the programmer is interested in pointers of t#pe Dpointer to struct 4omethingD. malloc() has to ,e forced to produce a pointer of the correct t#pe then and this is done ,# using the cast operator to mould it into shape. The cast operator casts pointers with a general form(type *) 4alue

Consider the following example of C source code which allocates space for a structure t#pe called +ome+truct and creates a correctl# aligned pointer to it, called ptr.
struct +ome+truct *ptr; char *malloc(); ptr = (struct +ome+truct *) malloc(siNeof(struct +omestruct));

This rather la,oured statement provides ,oth the memor# and the location of that memor# in a legal and t#pe;sensical wa#. The next section of this ,oo* discusses what we can do with d#namicall# allocated structures.

&nions
5 union is li*e a structure in which all the Imem,ers9 are stored at the same address. Clearl# the# cannot all ,e there at the same time. 1nl# one mem,er can ,e stored in such an o,?ect at an# one time, or it would ,e overwritten ,# another. Unions ,ehave li*e speciall# siAed storage containers which can hold man# different t#pes of data. 5 union can hold an# one of its mem,ers ,ut onl# at different times. The compiler arranges that a union t#pe varia,le is ,ig enough to handle the ?o,. The real purpose of unions is to prevent memor# fragmentation ,# arranging for a standard siAe for data in the memor#. +# having a standard data siAe we can guarantee that an# hole left when d#namicall# allocated memor# is freed will alwa#s ,e reusa,le ,# another instance of the same t#pe of union. This is a natural strateg# in s#stem programming where man# instances of different *inds of varia,les with a related purpose and stored d#namicall#.

6eclaration of unionUsing unions-

'eclaration
5 union is declared in the same wa# as a structure. .t has a list of mem,ers, which are used to mould the t#pe of o,?ect concerned.
union ntGrLloat

0 int ordinal; float continuous; A;

This declares a t#pe template. 3aria,les are then declared asunion ntGrLloat x(y(N;

5t different times the program is to treat x,y and N as ,eing either integers or float t#pes. <hen the varia,les are referred to as
x.ordinal = #;

the program sees x as ,eing an integer t#pe. 5t other times Bwhen x is referred to as x.continuousC it ta*es on another aspect- its alter ego, the float t#pe. Notice that x ,# itself does not have a value- onl# its mem,ers have values, x is ?ust a ,ox for the different mem,ers to share.

&sing unions
Unions are coded with the same constructions as structures. The dot . operator selects the different mem,ers for varia,le and the arrow -/ selects different values for pointers. The form of such statements isunionK4aria%le.mem%er; unionKpointer-/mem%er;

Unions are seldom ver# useful o,?ects to have in programs, since a program has no automatic wa# of *nowing what t#pe of mem,er is currentl# stored in the union t#pe. 1ne wa# to overcome this is to *eep a varia,le which signals the t#pe currentl# held in the varia,le. This is done ver# easil# with the aid of enumerated data. Consider the following *ind of unionunion ?hich3ype 0

int ordinal; float continuous; char letter; A;

This could ,e accompanied ,# an enumerate declaration such asenum 3ypes 0 N3( LEG13( DH1R A;

3aria,les could then go in pairsunion ?hich3ype x; enum 3ypes xKstatus;

which would ma*e union t#pe;handling straightforwardswitch (xKstatus) 0 case N3 : x.ordinal = #$; %rea6; case LEG13 : x.continuous = #$.$5; %rea6; case DH1R : x.letter = "*"; A

These varia,les could even ,e grouped into a structurestruct UnionKHandler 0 union ?hich3ype x; enum 3ypes xKstatus; A 4ar;

which would then re8uire statements such as4ar.x.ordinal = $; ptr-/x.ordinal = $; 4ar.xKstatus = DH1R;

and so on...

(uestions
%. ". G. . <hat is the difference ,etween a structure and a unionF <hat is a mem,erF .f x is a varia,le, how would #ou find out the value of a mem,er called mem. .f ptr is a pointer to a structure, how would #ou find out the value of a mem,er called mem. H. 5 union is a group of varia,les in a single pac*age. True or falseF

'ata /tructures
<ses for struct !ariables. Structure diagra$s. 6ata structures are organiAed patterns of data. The purpose of ,uilding a data structure is to create a pattern of information which models a particular situation clearl# and efficientl#. Ta*e the simplest *ind of data structure- the arra#. 5rra#s are good for storing patterns of information which loo* li*e ta,les, or share a ta,ular structure. 2or example, a chess ,oard loo*s li*e a two dimensional arra#, so a chess game would naturall# use a two dimensional arra# to store the positions of pieces on the chess ,oard. The aim of a data structure is to model real life patterns with program data. )ost real application programs re8uire a more complex data structure than C varia,les can offer@ often arra#s are not suita,le structures for a given application. To see this, consider an application example in which a program stores a map of the local countr#side. This program has to store information a,out individual towns and it has to ,e a,le to give directions to the user a,out how to get to particular towns from some reference point. .n real life, all of this information is most easil# conve#ed ,# means of a map, with towns9 vital statistics written on it. B4ee figure %.C The diagram shows such a simplified map of the surrounding land. This sort of map is, ideall#, ?ust what a computer ought to ,e a,le to store. The handicap is that the map does not loo* ver# computerish. .f the map is ever going to ,e stored in a computer it will need to loo* more mechanical. 5 transformation is needed. .n order to ma*e the map into a more computer;li*e picture, it must ,e drawn as a structure diagram.

5 structure diagram is a picture which shows how something is connected up. )ost often a structure diagram shows how a pro,lem is connected up ,# relating all the parts which go together to ma*e it up. .n this case, the structure diagram ?ust shows how program data are related to each other.

6ata 4tructure 6iagramsToolsProgramme 2or +uilding 6ata 4tructures4etting Up 5 6ata 4tructureExample 4tructures>uestions "(-

'ata /tructure 'iagra#s


Now examine figure ". This diagram is a data structure diagram- it is a diagram which shows how ,oxes of data must relate to one another in order to solve the pro,lem of the towns map. .t has ,een drawn, 8uite deli,eratel#, in a wa# which is intended to con?ure up some particular thoughts. The arrows tend to suggest that pointers will pla# a role in the data structure. The ,loc*s tend to suggest that sealed capsules or struct t#pe data will also pla# a role. Putting these two together creates the idea of a Itown structure9 containing pointers to neighouring villages which lie on roads to the North, 4outh, East and <est of the town, as well as the information a,out the town itself. This town structure might loo* something li*e thisstruct 3own 0 struct 3own *north; struct 3own *south; struct 3own *east; struct 3own *west; struct Eocal nfo help; A;

5ssume for now that Eocal nfo is a structure which contains all the information a,out a town re8uired ,# the program. This part of the information is actuall# irrelevant to the structure of the data ,ecause it is hidden inside the sealed capsule. .t is the pointers which are the main items of concern ,ecause it is pointers which contain information that ena,les a program to find its wa# around the map ver# 8uic*l#. .f the user of this imaginar# application program wished to *now a,out the town to the north of one particular place, the program would onl# have to refocus its attention on the new structure which was pointed to ,# the struct mem,er north and similarl# for other directions. 5 data structure is ,uilt up, li*e a model, ,# connecting struct t#pe varia,les together with pointers- these are the ,uilding ,loc*s. +# thin*ing of struct t#pes and pointers in terms of pictures, one ,egins to see how structures can ,e fashioned, in computer memor#, to loo* exactl# li*e the pro,lems which the# represent. <hat is interesting a,out data structure diagrams is the wa# in which the# resem,le the structure diagrams of C programs, which were drawn in chapter (. There is a simple reason for this similarit#- computer programs are themselves ?ust data structures in which the data are program instructions and the pointers and sealed ,oxes are function calls. The structure of a computer program is called a hierach#. 4ometimes the shape of data structures and programs are identical@ when this happens, a *ind of optimum efficienc# has ,een reached in conceptual terms. Programs which ,ehave exactl# li*e their data operate ver# simpl#. This is the reason wh# structure diagrams are so useful in programming- a structure diagram is a diagram which solves a pro,lem and does so in a pictorial wa#, which models the wa# we thin*.

"he "ools4 /tructures, Pointers and ',na#ic Me#or,


The tools of the data structure trade are struct t#pes and pointers. 6ata structures are ,uilt out of d#namicall# allocated memor#, so storage places do not need names- all a program needs to do is to *eep a record of a pointer, to a particular storage space, and the computer will ,e a,le to find it at an# time after that. Pointers are the *e#s which unloc* a program9s data. The reader might o,?ect to this ,# sa#ing that a pointer has to ,e stored in some C varia,le somewhere, so does a program reall# gain an#thing from wor*ing with pointersF The answer is #es, ,ecause pointers in data structures are invaria,l# chained together to ma*e up the structure. To understand this, ma*e a note of the following terms;oot This is a place where a data structure starts. Ever# chain has to start somewhere. The address of the root of a data structure has to ,e stored explicitl# in a C varia,le. 8inks 5 lin* is a pointer to a new struct t#pe. Lin*s are used to chain structures together. The address of the next element in a chain structure is stored inside the previous structure.

6ata structures do not have to ,e linear chains and the# are often not. 4tructures, after all, can hold an# num,er of pointers to other structures, so there is the potential to ,ranch out into an# num,er of new structures. .n the map example a,ove, there were four pointers in each structure, so the chaining was not linear, ,ut more li*e a latticewor*. <e need to thin* a,out where and how data structures are going to ,e stored. /emem,er that pointers alone do not create an# storage space- the# are onl# a wa# of finding out the contents of storage space which alread# exists. .n fact, a program must create its own space for data structures. The *e# phrase is d#namic storage- a program ma*es space for structures as new ones are re8uired and deletes space which is does not re8uire. The functions which perform this memor# allocation and release aremalloc() and free()

There are some advantages which go with the use of d#namic storage for data structures and the# are summariAed ,# the following points

4ince memor# is allocated as it is needed, the onl# restriction on data siAe is the memor# capacit# of the computer. <e don9t need to declare how much we shall use in advance. Using pointers to connect structures means that the# can ,e re;connected in different wa#s as the need arises. B6ata structures can ,e sorted, for example.C 6ata structures can ,e made up of lots of DlesserD data structures, each held inside struct t#pe storage. The limitations are few.

The remaining parts of this section aim to provide a ,asic plan or formula for putting data structures together in C. This is done with recourse to two example structures, which ,ecome two example programs in the next chapter.

Progra##e -or Building 'ata /tructures


.n writing programs which centre around their data, such as word processors, accounts programs or data,ase managers, it is extremel# important to plan data structures ,efore an# program code is written- changes in program code do not affect a data structure, ,ut alterations to a data structure impl# drastic changes to program code. 1nl# in some numerical applications does a data structure actuall# assist an algorithm rather than vice versa. The steps which a programmer would underta*e in designing a data structure follow a ,asic pattern

Group all the data, which must ,e stored, together and define a struct t#pe to hold them. Thin* of a pattern which reflects the wa# in which the data are connected and add structure pointers to the struct definition, to connect them. 6esign the programming algorithms to handle the memor# allocation, lin* pointers and data storage.

/etting &$ 3 'ata /tructure


1nce the ,asic mould has ,een cast for the ,uilding ,loc*s, a program actuall# has to go through the motions of putting all the pieces together, ,# connecting structures together with pointers and filling them up with information. The data structure is set up ,# repeating the following actions as man# times as is necessar#.

6efine a struct t#pe. 2or examplestruct 3own 0 struct 3own *north; struct 3own *south; struct 3own *east; struct 3own *west; struct Eocal nfo help; A;

6eclare two pointers to this t#pestruct 3own *ptr(*root;

1ne of these is used to hold the root of the data structure and the other is used as a current pointer.

5llocate memor# for one structure t#peroot = (struct 3own *) malloc(siNeof(struct 3own));

+e careful to chec* for errors. root will ,e NULL if no memor# could ,e allocated.

.nitialiAe the mem,ers of the structure with statements such asroot-/north = NUEE; root-/south = NUEE; root-/help.age = 8:; )* if age is a mem%er *) )* of struct Eocal nfo *)

This sets the pointers north and south to the value NUEE, which conventionall# means that the pointer does not point an#where.

<hen other structures have ,een created, the pointers can ,e assigned to themptr = (struct 3own *) malloc(siNeof(struct 3own)); ptr-/north = NUEE; ptr-/south = NUEE; )* etc.. initialiNe mem%ers *) root-/north = ptr;

This last statement connects the new structure onto the north ,ranch of root.

pointer assignments tell the program handling the data structure when it has come to the edge of the structure- that is when it has found a pointer which doesn9t lead an#where.
NUEE

%*a#$le /tructures
Two data structures of thids *ind are ver# common- the linked list and the %inary tree and ,oth wor* upon the principles outlined a,ove B.n fact the# are ?ust different manifestations of the same thing.C 5 lin*ed list is a linear se8uence of structures ?oined together ,# pointers. .f a structure diagram were drawn of a lin*ed list, all the storage ,loc*s in it would lie in a straight line, without ,ranching out.
struct list 0 dou%le 4alue; struct list *succ; A;

5 lin*ed list has onl# a single pointer per structure, which points to the successor in the list. .f the ,loc*s were la,elled 5 + C 6 E... then + would ,e the successor of 5@ C would ,e the successor of + and so on. Lin*ed lists have two advantages over one dimensional arra#s- the# can ,e sorted easil# Bsee diagramC and the# can ,e made an# length at all. 5 ,inar# tree is a se8uence of structures, each of which ,ranches out into two new ones.
struct 9inary3ree 0 )* other info *) struct 9inary3ree *left; struct 9inary3ree *right; A *tree = NUEE;

5 ,inar# tree structure has two pointers per struct t#pe. This is useful for classif#ing data

on a greater thanEless than ,asis. /ight and left ,ranches are ta*en to mean Igreater than9 and Iless than9 respectivel#. The programs which handle these data structures are written in the form of complete, usa,le application programs. The# are simple ,# professional standards, ,ut the# are long ,# ,oo* standards so the# are contained in a section ,# themselves, along with their accompan#ing programmers9 documentation, 4ee Example Programs chapter.

(uestions
%. <hat is a structure diagramF ". 7ow are data lin*ed together to ma*e a data structureF G. Ever# separate struct t#pe in a data structure has its own varia,le name. True or falseF . 7ow are the mem,ers of structures accessed in a data structureF H. <rite a statement which creates a new structure of t#pe Dstruct +inar#TreeD and finds its address. 4tore that address in a varia,le which is declared as follows:. ;. struct 9inary3ree *ptr;

'. <rite a small program which ma*es a lin*ed list, three structures long and assigns all their data to ,e Aero. Can #ou automate this program with a loopF Can #ou ma*e it wor* for an# num,er of structuresF

)ecursion
The dae$on which swallowed its tail. This section is a,out program structures which can tal* a,out themselves. <hat happens to a function which ma*es a call itselfF Examine the function ,elow?ellKLunction () 0 )* ... other statements ... *) ?ellKLunction (); A

is said to ,e a recursive function. .t is defined in terms of itself- it contains itself and it calls itself. .t swallows its own tail: The act of self;reference is called recursion. <hat happens to such a function when it is called in a C programF .n the simple example a,ove, something dramatic and fatal happens. The computer, naturall#, ,egins executing the statements in the function, inside the curl# ,races. This much is onl# normal- programs are designed to do this and the computer could do no more and no less. Eventuall# the program comes upon the statement ?ellKLunction(); and it ma*es a call to that function again. .t then ,egins executing statements in ?ellKfunction(), from the ,eginning, as though it were a new function, until it comes upon the statement ?ellKLunction() and then it calls the function again....
?ellKLunction()

This *ind of function calling scenario is doomed to continue without end, as, each time the function is called, it is inevita,l# called again. The computer ,ecomes totall# consumed with the tas* of calling ?ellKLunction() over and over. .t is apparentl# doomed to repeat the same procedure for ever. 1r is itF

2unctions and The 4tac*Levels and <ellsTame /ecursion and 4elf;4imilarit#4imple Example without a 6ata 4tructure4imple Example <ith a 6ata 4tructure5dvantages and 6isadvantages of /ecursion/ecursion and Glo,al 3aria,les>uestions "'-

-unctions and "he /tack


<e should thin* a,out the exact se8uence of events which ta*es place when a function is called in a program. This will help to cast some light on the mechanics of recursion and

recursive functions. <hen a function is called, control passes from one place in a program to another place. The statements in this new region of the program are carried out and then control returns to a statement immediatel# following the one which made the function call. +ut how does the computer *now where it must go ,ac* to, when it has finished with a function callF .t is suddenl# thrown into a wildl# different region of the memor# and finds itself executing statements there. 7ow can it get ,ac* againF 5 diagram does not answer this 8uestion- program structure diagrams hide this detail from view.

view.

function#() ) ) 2 2 function5() ) 2

function$() ) 2

The answer to this puAAle is that the computer *eeps a record of the addresses of the places to which it must return, no matter how man# times functions are called. .t does this ,# ,uilding a special data structure called a stac6.

5 stac* is 8uite literall# a pile of data, organiAed in the memor#. .nformation is placed on top of a stac* and ta*en from the top. .t is called a last in first out BL.21C structure ,ecause the last thing to go on the top of a stac* is alwa#s the first thing to come off it. C organiAes a stac* structure when it runs a program and uses it for storing local varia,les and for *eeping trac* of where it has to return to. <hen it calls a function, it leaves itself a reminder, on the top of its program stac*, which tells it where it has to go to when it has finished executing that function. C management ma*es sure that it does not put an#thing else on top of that reminder to spoil the flow of control. <hen a function is finished, the program ta*es the first message from the top of the stac* and carries on executing statements at the place specified ,# the message. Normall# this method wor*s perfectl#, without an# pro,lems at all- functions are called and the# return again@ the stac* grows and shrin*s and all is well.

<hat happens when a recursive function, li*e ?ellKLunction() calls itselfF The s#stem wor*s as normal. C ma*es a note of the place it has to return to and puts that note on top of the stac*. .t then ,egins executing statements. <hen it comes to the call ?ellKLunction() again, it ma*es a new note of where it has to come ,ac* to and deposits it on top of the stac*. .t then ,egins the function again and when it finds the function call, it ma*es a new note and puts on the top of the stac*.... 5s this process continues, the memor# gets filled up with the program9s messages to itself- the stac* of messages gets larger and larger. 4ince the function has no chance of returning control to its caller, the messages never get ta*en off the stac* and it ?ust ,uilds up. Eventuall# the computer runs out of memor# and the computer crashes or interrupts the program with a fatal error message.

Levels and 1ells


5 stac* is made up of frames or levels. Each time a function is called, the program is said to drop down a level. This is the reason for structure comments li*e)****************************************************) )* Ee4el # *) )****************************************************)

in the programs in this ,oo*. The main() function is at level ! ,ecause it is the root of the program. .f main() calls an# functions at all, control drops down to level one. <hen a level one function returns, it hands control ,ac* to level Aero. These level num,ers actuall# count the height of the program stac* at an# point in a program. The level num,er is the num,er of messages or reminders on the stac*. 5 function li*e ?ellKLunction() digs itself a well of infinite depth. .t punches a great hole in a program@ it has no place in a levelled structure diagram. The function is pathological ,ecause it causes the stac* fill up the memor# of the computer. 5 ,etter name for this function would ,e+tac6G4erflow() 0 +tac6G4erflow(); A )* Dauses stac6 to grow out of control *)

"a#e )ecursion and /elf>/i#ilarit,


/ecursion does not have to ,e so dramaticall# disastrous as the example given. .f recursion is tamed, it provides perhaps the most powerful wa# of handling certain *inds of pro,lem in programming, particularl# concerning data structures. Earlier we remar*ed that programs and data structures aim to model the situation the# deal with as closel# as possi,le. 4ome pro,lems are made up of man# levels of detail Bsee the introduction to this tutorialC and the details are identical at all levels. 4ince recursion is a,out functions which contain themselves at all levels, this tends to suggest that

recursion would ,e useful for dealing with these self;similar pro,lems. 6ata structures are prime candidates for this ,ecause the# are made up of identical structure t#pes, connected together in a wa# which ma*e them loo* li*e programs connected up ,# function calls. /ecursive functions can ,e tamed ,# ma*ing sure that there is a safe wa# exit them, so that recursion onl# happens under particular circumstances. The aim is to control the num,er of times that recursion ta*es place ,# ma*ing a decision a,out what happens in the function- the decision a,out whether a function calls itself or not. 2or example, it is eas# to ma*e ?ellKLunction recurse four times onl#, ,# ma*ing a test?ellKLunction(nooftimes) int nooftimes; 0 if (nooftimes == @) 0 return (@); A else 0 ?ellKLunction(nooftimes-#); A A

5 call of ?ellLunction(7) would ma*e this function drop down four stac* levels and then return. Notice the wa# in which the if..else statement shields the program from the recursion when nooftimes e8uals Aero. .t effectivel# acts as a safet# net, stopping the programming from plunging down the level well infinitel#.

/i#$le %*a#$le without a 'ata /tructure


5 completel# standard example of controlled recursion is the factorial Bor GammaC function. This is a mathematical function which is important in statistics. B)athematicians also deal with recursive functions@ computer programs are not alone in this.C The factorial function is defined to ,e the DproductD BmultiplicationC of all the natural Bunsigned integerC num,ers from % to the parameter of the function. 2or examplefactorial(7) == # * $ * 5 * 7 factorial(:) == # * $ * 5 * 7 * 8 * : == $7 == ;$@

2ormall#, the factorial function is defined ,# two mathematical statementsfactorial (n) = n * factorial(n-#)

and

factorial (@) = #

The first of these statements is recursive, ,ecause it defines the value of factorial(n) in terms of the factorial function of Bn;%C. This strange definition seems to want to lift itself ,# its ver# ,ootstraps: The second statement saves it, ,# giving it a reference value. The factorial function can ,e written down immediatel#, as a controlled recursive functionfactorial (n) unsigned int n; 0 if (n == @) 0 return (#); A else 0 return (n * factorial(n-#)); A A

To see how this wor*s, tr# following it through for n e8uals three. The statementfactorial (5);

causes a call to ,e made to factorial(). The value of n is set to three. factorial() then tests whether n is Aero Bwhich it is notC so it ta*es the alternative ,ranch of the if..else statement. This instructs it to return the value of5 * factorial(5-#)

.n order to calculate that, the function has to call factorial recursivel#, passing the value BG;%C or " to the new call. The new call ta*es this value, chec*s whether it is Aero Bit is notC and tries to return the value $ * factorial(#). .n order to wor* this out, it needs to call factorial again, which chec*s that n is not ! Bit is notC and so tries to return # * factorial(@). 2inall#, it calls factorial(@) which does not call factorial an# more, ,ut starts unloading the stac* and returning the values. The expression goes through the following steps ,efore finall# ,eing evaluatedfactorial (5) == == == == 5 5 5 5 * * * * factorial($) ($ * factorial(#)) ($ * (# * factorial(@))) ($ * (# * #)))

== 5 * $ * # * #

Tr# to write this function without using recursion and compare the two.

/i#$le %*a#$le 1ith a 'ata /tructure


5 data structure earns the name recursive if its structure loo*s identical at ever# point within it. The simplest recursive structure is the lin*ed list. 5t ever# point in a lin*ed list, there are some data of identical t#pe and one pointer to the next structure. The next simplest structure is the ,inar# tree- this structure splits into two at ever# point. .t has two pointers, one which ,ranches left and one which ,ranches to the right. Neither of these structures goes on for ever, so it seems reasona,le to suppose that the# might ,e handled easil# using controlled recursive functions. is a function which releases the d#namic memor# allocated to a lin*ed list in one go. The pro,lem it faces is this- if it deletes the first structure in the list, it will lose information a,out where the rest of the list is, ,ecause the pointer to the successor of a structure is held in its predecessor. .t must therefore ma*e a note of the pointer to the next structure in the list, ,efore it deletes that structure, or it will never ,e a,le to get ,e#ond the first structure in the list. The solution is to delete the list ,ac*wards from last to first using the following recursive routine.
deletetoend() )* structure definition *) struct list 0 )* some other data mem%ers *) struct list *succ; A; )**************************************************************) struct list *deletetoend (ptr) struct list *ptr; 0 if (ptr I= NUEE) 0 deletetoend (ptr-/succ); releasestruct (ptr); A return (NUEE); A )**************************************************************) releasestruct (ptr) struct list *ptr; 0 if (free((char *) ptr) I= @) 0 printf (&<B9UR XF@)36t<t+trctY memory release failure2n&); A A )* release memory %ac6 to pool *)

<e suppl# a pointer to the place we would li*e the list to end. This need not ,e the ver# ,eginning- it could ,e an# place in the list. The function then eliminates all structures after that point, up to the end of the list. .t does assume that the programmer has ,een careful to ensure that the end of the list is mar*ed ,# a NUEE pointer. This is the conventional wa# of denoting a pointer which does not point an#where. .f the pointer supplied is alread# NUEE then this function does nothing. .f it is not NUEE then it executes the statements enclosed ,# the if ,races. Notice that deletetoend() calls itself immediatel#, passing its successor in the list as a parameter. (ptr-/succ) The function *eeps doing this until it finds the end on the list. The ver# last;called deletetoend() then reaches the statement releasestruct() which frees the memor# ta*en up ,# the last structure and hands it ,ac* to the free memor# pool. That function conse8uentl# returns and allows the second;last deletetoend() to reach the releasestruct() statement, releasing the second last structure Bwhich is now on the end of the listC. This, in turn, returns and the process continues until the entire list has ,een deleted. The function returns the value NUEE at each stage, so that when called, deletetoend() offers a ver# elegant wa# of deleting part or all of a lin*ed liststruct list *newlast; newlast-/succ = deletetoend (newlast-/succ); ptr = deletetoend (ptr);

newlast then ,ecomes the new end of the list, and its successor is NULLified in a single statement.

3dvantages and 'isadvantages of )ecursion


<h# should programmers want to clutter up programs with techni8ues as mind ,oggling as recursion at allF The great advantage of recursion is that it ma*es functions ver# simple and allows them to ,ehave ?ust li*e the thing the# are attempting to model. Unfortunatel# there are few situations in which recursion can ,e emplo#ed in a practical wa#. The ma?or disadvantage of recursion is the amount of memor# re8uired to ma*e it wor*- do not forget that the program stac* grows each time a function call is made. .f a recursive function ,uried itself a thousand levels deep, a program would almost certainl# run out of memor#. There is also the slight danger that a recursive function will go out of control if a program contains ,ugs.

)ecursion and 5lo al 0aria les


Glo,al varia,les and recursion do not mix well. )ost recursive routines onl# wor* ,ecause the# are sealed capsules and what goes on inside them can never affect the outside world. The onl# time that recursive functions should attempt to alter glo,al storage is when the function concerned operates on a glo,al data structure, as in the example a,ove. To appreciate the danger, consider a recursive function, in which a second function alterREG91E() accidentall# alters the value of REG91E in the middle of the function-

int REG91E = -$; recursion () 0 if (PPREG91E == @) 0 return (@); A alterREG91E(); recursion(); A )* another function which alters REG91E *)

This function is treading a fine line ,etween safet# and digging its own recursive grave. .f alterREG91E() ma*es REG91E more negative, as fast as PP can ma*e it more positive then REG91E will never ,e a,le to satisf# the condition of ,eing Aero and it will go on ma*ing recursive calls, never returning. .f alterREG91E() ma*es the mista*e of setting REG91E to a positive value, then the PP operator in recursion() can onl# ma*e REG91E larger and it will never ,e a,le to satisf# the condition that REG91E == @ and so again the function would never ,e a,le to return. The stac* would fill up the memor# and the program would plunge down an unending recursive well. .f glo,al varia,les and parameters are used instead, this difficult# can ,e controlled much more easil#. alterREG91E() cannot alter a varia,le in recursion() ,# accident, if onl# local varia,les are used, ,ecause it onl# wor*s with its own local copies of parameters and varia,les which are loc*ed awa# in a sealed capsule, out of harm9s wa#.

(uestions
%. <hat is a recursive functionF ". <hat is a program Dstac*D and what is it for. G. 4tate the ma?or disadvantage of recursion.

%*a#$le Progra#s
The aim of this section is to provide two su,stantial examples of C, which use the data structures descri,ed in section "'.

4tatistical 6ata 7andlerListing stat3aria,le Cross /eferencer-

/tatistical 'ata Handler


The first program is a utilit# which allows the user to t#pe sets of floating point data into an editor and to calculate the mean, standard deviation...and so on, of those data. The program is capa,le of loading and saving the data to dis*, as well as ,eing a,le to handle

several sets of data at once. The editor wor*s in insert or overwrite modes. The program is menu driven and its operation should ,e reasona,l# self explanator#, so it is presented with rather sparse documentation.

The editor.nsert 1verwrite>uitting sectionProgram listing stat-

"he %ditor
5 simple machine independent editor is provided for entering data. The editor first as*s the user whether the current num,er of sets of data is to ,e altered. The default value is Aero so, when data are t#ped in for the first time, this should ,e set up, ,# responding = for #es. Up to twent# independent sets of data can ,e used. This num,er is set at the start and it is held in the memor# and saved to dis* with data files. .f the num,er of sets is reduced at an# time, the top sets are cut off from the calculations, ,ut the# are not lost forever, provided the num,er is changed ,ac* to include them ,efore the# are saved to dis*, since the num,er of sets is used as an upper ,ound in a for loop- it does not actuall# alter the memor#. )ore sets can ,e added at an# time ,# ma*ing this value larger.

Insert:+verwrite
5 pro?ect file can ,e edited in either insert mode or overwrite mode. 2iles which contain no data ma# onl# ,e edited insert mode. The editor senses this and selects the mode automaticall#. .n insert mode the user is prompted for values. T#pe !.! in place of an entr# to get out of this mode. .n overwrite mode the user is offered each entr# in turn. .f a non digit character is t#ped in Bsuch as a . BdotC or a - BdashC etc..C the value of an entr# is not altered. 7owever, if a new value is entered, the new value will replace the old one. +# default, the values are offered in turn from % to the final value. 7owever, on selecting overwrite mode, the user is prompted for a starting value, and the values are offered from the starting num,er to the end. This is to avoid the rather tedious process of wor*ing through all the entries which are not re8uired in a s#stem independent wa#.

(uitting /ections
<hen 8uitting sections in which the user is supposed to enter data, the convention is that t#ping a Aero value B!.! for a time, ! in an# other instanceC is a signal to ,rea* out of a section. T#ping !.! while editing in insert mode causes the editor to 8uit.

"he Progra# Listing


The program includes three li,rar# files, which are used for the following purposes.
-include .stdio.h/ -include .ctype.h/

4tandard .1 eader file Contains character .6 macros

-include .math.h/

.ncludes math function declarations The flow of program logic is most easil# descri,ed ,# means of a program structure diagram. The diagram shows the structure of function calls within the program and this can ,e related to the listing. The general scheme of the program is this-

%. 3arious flags concerning the data structure are cleared. ". 5 menu is printed and the program c#cles through the menu options. G. The editor determines the data group to ,e edited, updates the screen with the data in the current group and loops through insert or overt#pe editing until the user 8uits. . The anal#sis calls custom functions which scan through the data structure calculating the relevant 8uantities. H. 3arious tool*its perform run of the mill activities. The data structure of this program is an arra# of lin*ed lists. The arra# provides the roots of several independent lin*ed lists- one for each group of data. These lin*ed lists are attended to ,# tool*it routines and ,# special functions such as o4er().

Listing
)************************************************************) )* *) )* +tatistical Dalculator *) )* *) )************************************************************)

-include .stdio.h/ -include .ctype.h/ -include .math.h/ )***********************************************************) )** Janifest Donstants ) Jacros ) +tatic Saria%les **) )***********************************************************) -define -define -define -define -define -define -define -define -define 3RUB L1E+B RR,+ D1RBLUEE\ L1+3 NG3FBRG BN<J1RW NG3BN<J1RW 9 RNUJ # @ $@ )* No grps which can %e handled *) # @ # -#.# @ #e5@@ )* list data *) )* proUect name *)

int <13+B3+ = @; short <1313HBRB = L1E+B; char *L+, = &..........................&;

)**********************************************************) )** +3RUD3URB+ **) )**********************************************************) struct list 0 dou%le 4alue; struct list *succ; A; struct Slist 0 struct list *datptr; int datathere; A <ataXRR,+Y; )***********************************************************) )** EBSBE @ : Jain ,rogram **) )***********************************************************) main () 0 char get6ey(); clrflags(); while (3RUB) 0 Jenu(); switch (get6ey()) 0 case "#" : edit(noofgroups()); %rea6; case "$" : Eoad+a4e();

A A

%rea6; case "5" : 1nalyse(); %rea6; case "O" : if (wantout(D1RBLUEE\)) Ouit(); A

)************************************************************) )** EBSBE # **) )************************************************************) clrflags() 0 short i; for (i=#; i.=RR,+; iPP); 0 <ataXiY.datathere = L1E+B; <ataXiY.datptr = NUEE; A A )***********************************************************) Jenu () 0 DER+DRN(); printf (&2n+tatistical Dalculator S#.@2n2n2n&); printf printf printf printf printf A (&# : Bdit <ata Liles2n2n&); (&$ : ,roUect Liles2n2n&); (&5 : 1nalyse Liles2n2n&); (&O : ]uit2n2n&); (&2nBnter Dhoice and RB3URN : &); )* nitialiNe a 4irtual list *)

)*************************************************************) edit (noKgrps) int noKgrps; 0 char s(status()(get6ey(); int i(stop = L1E+B(ctr; 4oid sa4eproUect(); dou%le o4er()(t(correct(getfloat(); struct list *ptr(*here(*eolist()( *install()(*startfrom(); while (3RUB) 0 i = whichgroup(); switch (s = status(i)) 0 case "i": for (here = eolist(i(Mctr); 3RUB; ctrPP) 0 )* Bdit a lin6ed list *)

updatescrn (i(s); printf(&'d:&(ctr); if ((t = getfloat ()) == @) %rea6; here = install (here(t(i); A printf (&2n2nLile closed2n2n&); %rea6; case "o": for (ptr=startfrom(Mctr(i); ptr I= NUEE; ptr = ptr-/succ) 0 if (ctr ' 7 == #) updatescrn (i(s); correct = o4er(ctrPP(ptr-/4alue); ptr-/4alue = correct; A %rea6; case "s": sa4eproUect(); %rea6; case "l": loadproUect(); %rea6; case "O": stop = wantout(L1+3); A if (stop) %rea6; A

)************************************************************) noofgroups () 0 char ch(get6ey(); printf (&,roUect currently holds 'd groups2n2n&(<13+B3+); printf (&1lter groups or BditV (1)B)&); ch = get6ey(); switch (tolower(ch)) 0 case "a" : printf (&2nHow many groups for this fileV (@..'d)2n2n&(RR,+); return (<13+B3+ = getint(@(RR,+)); case "e" : return (<13+B3+); A A )*************************************************************) Eoad+a4e () 0 char ch(get6ey(); DER+DRN(); printf (&2nDurrent ,roUect 's2n2n2n&( L+,); printf (&Eoad new proUect or +a4e current one (E)+)]uit) V2n2n&); ch = get6ey(); )* ,roUect options *) )* Dhec6 no. of data groups *)

switch (tolower(ch)) 0 case "l" : if (sure()) 0 <1313HBRB = loadproUect (); A %rea6; case "s" : if (sure()) 0 sa4eproUect (); A case "O" : A A )************************************************************) 1nalyse () )* ?or6 out some typical Ouantities *)

0 char get6ey(); dou%le mean()( mn( milli6an(); int i; printf (&1nalysis of <ata2n2n&); for (i = #; i .= <13+B3+; iPP) 0 mn = mean(i); printf (&Jean 4alue of group '$d : 'f2n&(i(mn); stdde4s(mn); printf (&Jilli6an 4alue 'd 'lg:2n&(i(milli6an(i)); NB?E NB(); A get6ey(); A )************************************************************) Ouit () 0 short i; struct list *deletetoend(); for (i = @; i .= <13+B3+; iPP) 0 deletetoend (<ataXiY.datptr); A exit(@); A )************************************************************) )* EBSBE $ *) )************************************************************) 4oid sa4eproUect () )* ]uit program M tidy *)

0 L EB *dfx; char *filename()(ch(get6ey(); struct list *ptr; int i; if ((dfx = fopen (filename()(&w&)) == @) 0 printf (&Dannot write to file2n,ress a 6ey2n&); ch = get6ey(); return; A fprintf (dfx(&'ld2n&(<13+B3+); for (i=#; i .= <13+B3+; iPP) 0 for (ptr = <ataXiY.datptr; ptr I= NUEE; ptr = ptr-/succ) 0 fprintf (dfx(&'lf 2n&(ptr-/4alue); A fprintf (dfx(&'f2n&(BN<J1RW); fprintf (dfx(&'d2n&(<ataXiY.datathere); A while (fclose (dfx) I= @) 0 printf (&?aiting to close &); A %lan6line (); return; A )************************************************************) loadproUect () )* Eoad new list M delete old *)

0 L EB *dfx; char *filename()(ch(get6ey(); int r(i; dou%le t = #.@; struct list *ptr(*install()(*deletetoend(); if ((dfx = fopen(filename()(&r&)) == NUEE) 0 printf (&Lile cannot %e read2n,ress any 6ey2n&); ch = get6ey(); return (@); A fscanf (dfx(&'ld&(M<13+B3+); for (i = #; i .= <13+B3+; iPP) 0 t = NG3BN<J1RW; <ataXiY.datptr = deletetoend(<ataXiY.datptr); <ataXiY.datathere = L1E+B;

for (ptr = <ataXiY.datptr; t I= BN<J1RW;) 0 fscanf (dfx(&'lf&(Mt); if (t I= BN<J1RW) 0 ptr = install (ptr(t(i); A A fscanf (dfx(&'ld&(Mr); <ataXiY.datathere = r; A while (fclose(dfx) I= @) 0 printf (&?aiting to close file&); A %lan6line(); return (3RUB); A )**********************************************************) whichgroup () 0 int n = @; printf (&2n2nBdit account num%er: &); n = getint (@(<13+B3+); if (n == @) 0 printf (&]uitI2n&); A return (n); A )***********************************************************) char status (i) int i; 0 char stat; if (i==@) 0 stat = "O"; A else 0 if (<ataXiY.datathere) 0 printf (& nsert)G4erwrite)Eoad)+a4e)]uitV&); stat = get6ey(); stat = tolower(stat); A else 0

stat = "i"; A A return (stat); A )************************************************************) updatescrn (grp(status) int grp; char status; 0 int ctr=@; struct list *ptr; DER+DRN(); printf (&2n+tatistical Bditor S#.@2n2n&); printf (&2n3his proUect file contains 'd groups.2n&(<13+B3+); for (ptr = <ataXgrpY.datptr; (ptr I= NUEE); ptr=ptr-/succ) 0 if ((ctr ' 5) == @) NB?E NB(); printf (& ('$d) '#$g &(ctrP#((ptr-/4alue)); ctrPP; A printf (&2n2nBditing Rroup 'd. Dontains 'd entries switch (tolower(status)) 0 case "i" : printf (& N+BR3 JG<B **2n&); %rea6; case "o" : printf (&GSBR?R 3B JG<B **2n&); A NB?E NB(); A )**********************************************************) dou%le o4er (n(old) int n; dou%le old; 0 dou%le correct = @; printf (&Bntry '-$d : &(n); scanf(&'lf&(Mcorrect); s6ipgar%(); if (correct == @) 0 return (old); A else 0 return(correct); )* Bdit o4ertype mode *) ** &(grp(ctr); )* Update editor screen *)

)************************************************************) dou%le mean (i) int i; 0 struct list *ptr; dou%le sum; int num; sum = num = @; for (ptr = <ataXiY.datptr; ptr I= NUEE; ptr=ptr-/succ) 0 sum P= ptr-/4alue; num PP; A return (sum)num); A )**************************************************************) stdde4s (mean(i) dou%le mean; int i; 0 dou%le sum(num(4ar; struct list *ptr; sum = num = @; for (ptr = <ataXiY.datptr; ptr I= NUEE; ptr=ptr-/succ) 0 sum P= (ptr-/4alue - mean) * (ptr-/4alue - mean); num PP; A 4ar = sum)num; )* &%iased& 4alue *) )* find 4ariance)std de4iation *) )* find mean a4erage *)

printf (&Sariance 'd = 'f2n&(i(4ar); printf (&+td de4iation 'd = 'f2n&(i(sOrt(4ar)); A )************************************************************) dou%le milli6an (i) int i; 0 dou%le temp(record = 9 RNUJ; struct list *ptr#(*ptr$; for (ptr# = <ataXiY.datptr; ptr# I= NUEE; ptr# = ptr#-/succ) 0 )* smallest diffnce %etween $ data *)

for (ptr$=<ataXiY.datptr; ptr$I=ptr#; ptr$=ptr$-/succ) 0 temp = (ptr#-/4alue) - (ptr$-/4alue); if (19+(temp) . record) 0 record = 19+(temp); A A A return(record); A )************************************************************) )* EBSBE 5 *) )************************************************************) char *filename () 0 do

0 printf (&Bnter filename : &); scanf (&'s&(L+,); s6ipgar%(); A

while (strlen(L+,) == @); return (L+,); A )************************************************************) )* 3ool6it data structure *) )************************************************************) struct list *eolist(i(c) int i(*c; 0 struct list *ptr(*p = NUEE; *c = #; for (ptr = <ataXiY.datptr; ptr I= NUEE; ptr = ptr-/succ) 0 PP(*c); p = ptr; A return (p); A )*************************************************************) struct list *startfrom (ctr(i) int *ctr(i; 0 struct list *ptr(*p = NUEE; int U = @; )* Lind ith node in list *) )* +ee6 end of a lin6ed Slist *)

printf (&G4ertype starting from which entry&); *ctr = getint(#(>>); for (ptr=<ataXiY.datptr; (ptr I= NUEE) MM (UPP I= *ctr); ptr=ptr-/succ) 0 p = ptr; A return (p); A )*************************************************************) struct list *install (ptr(t(i) struct list *ptr; dou%le t; int i; 0 struct list *thispos( *newstruct(); if ((thispos = newstruct()) == NUEE) 0 warning(); printf (&<B9UR **: Lree memory pool is empty&); exit(@); A if (I<ataXiY.datathere) 0 <ataXiY.datptr = thispos; <ataXiY.datathere = 3RUB; A else 0 ptr-/succ = thispos; A thispos-/4alue = t; thispos-/succ = NUEE; return (thispos); A )************************************************************) struct list *deletetoend (ptr) struct list *ptr; 0 if (ptr I= NUEE) 0 deletetoend (ptr-/succ); releasestruct (ptr); A return (NUEE); )* RBDUR+ SB ?BEE - returns NUEE for easy deletion of call ptr *) )* install item at thispos *)

A )************************************************************) struct list *newstruct () )* 1llocate space for new item *) 0 char *malloc(); return ((struct list *) malloc(siNeof(struct list))); A )***********************************************************) releasestruct (ptr) struct list *ptr; 0 if (free((char *) ptr) I= @) 0 printf (&<B9UR XF@)36t<t+trctY memory release faliure2n&); A A )********************************************************) )* 3ool6it DGN+GEB Gutput *) )********************************************************) DER+DRN () 0 printf (&2f&); A )*********************************************************) newline () 0 printf (&2n&); A )**********************************************************) %lan6line () 0 printf (& A 2r&); )* release memory %ac6 to pool *)

)**********************************************************) warning () 0 putchar("2;"); A )***********************************************************) )*** 3ool6it DGN+GEB nput **)

)***********************************************************) wantout (%ecareful) int %ecareful; 0 if (%ecareful) 0 printf (&Really OuitV (\)N)2n&); if (yes()) return (3RUB); else return (L1E+B); A return (3RUB); A )*************************************************************) sure (%ecareful) int %ecareful; 0 if (%ecareful) 0 printf (&1re you sureV (\)N)2n&); if (yes()) return (3RUB); else return (L1E+B); A return (3RUB); A )***********************************************************) yes () )* %oolean response \)N Ouery *) )* 1re you sure : %oolean *) )* Bxit from a section *)

0 while (3RUB) 0 switch (get6ey()) 0 case "y" : case "\" : return (3RUB); case "n" : case "N" : return (L1E+B); A A A )***********************************************************) char get6ey () 0 char ch; scanf (&'c&(Mch); s6ipgar%(); return (ch); A )***********************************************************) )* get single character *)

getint (a(%) int a(%; 0 int p( i = a - #;

)* return int %etween a and % *)

for (p=@; ((a / i) QQ (i / %)); pPP) 0 printf (&V&); scanf (&'d&(Mi); if (p / 5) 0 s6ipgar%(); p = @; A A s6ipgar%(); return (i); A )***********************************************************) dou%le getfloat () 0 dou%le x = @; printf (&V &); scanf (&'lf&(Mx); s6ipgar%(); return (x); A )************************************************************) s6ipgar%() )* +6ip input gar%age corrupting scanf *) )* return long float *)

0 while (getchar() I= "2n"); A )* end *)

0aria le !ross )eferencer


5 varia,le cross referencer is a utilit# which produces a list of all the identifiers in a C program Bvaria,les, macros, functions...C and lists the line num,ers of those identifiers within the source file. This is sometimes useful for finding errors and for spotting varia,les, functions and macros which are never used, since the# show up clearl# as identifiers which have onl# a single reference. The program is listed here, with its line num,ers, and its output Bapplied to itselfC is supplied afterwards for reference. The

structure diagram illustrates the operation of the program.

Listing Cref.c1utput of Cross /eferencerCommonts on cref.c-

Listing !ref.c
# $ 5 7 8 : ; = > #@ ## #$ #5 )********************************************************) )* *) )* D programming utility : 4aria%le referencer *) )* *) )********************************************************) )* +ee notes a%o4e *) -include .stdio.h/ -include .ctype.h/ -define 3RUB -define L1E+B # @

#7 #8 #: #; #= #> $@ $# $$ $5 $7 $8 $: $; $= $> 5@ 5# 5$ 55 57 58 5: 5; 5= 5> 7@ 7# 7$ 75 77 78 7: 7; 7= 7> 8@ 8# 8$ 85 87 88 8: 8; 8= 8> :@ :# :$ :5 :7 :8 :: :; := :> ;@ ;# ;$

-define -define -define -define int char char char

<UJJ\ J1C+3R J1C <+ FB ?GR<319EB

@ 8#$ 5$ 55 )* Dontains line no. in file )* nput 9ULLBR for <s )* Durrent input character )* macro)pointer flag *) *) *) *)

E NBDGUN3 = #; 9ULLBRXJ1C <+ FBY; DH; +,BD 1EDH1R;

)**********************************************************) )* 319EB *) )**********************************************************) char *?GR<319EB X?GR<319EBY = 0 &auto& ( &%rea6& ( &case& ( &char& ( &const&( &continue&( &default& ( &do& ( &dou%le& ( &else& ( &entry& ( &enum& ( &extern& ( &float& ( &for& ( &goto& ( &if& ( &int& ( &long& ( &register&( &return& ( &short& ( &signed& ( &siNeof& ( &static& ( &struct& ( &switch& ( &typedef& ( &union& ( &unsigned&( &4oid& ( &4olatile&( &while& ( A; )********************************************************) )** +3RUD3URB+ **) )********************************************************) struct heap 0 )* 3a%le of res4d words *)

;5 ;7 ;8 ;: ;; ;= ;> =@ =# =$ =5 =7 =8 =: =; == => >@ ># >$ >5 >7 >8 >: >; >= >> #@@ #@# #@$ #@5 #@7 #@8 #@: #@; #@= #@> ##@ ### ##$ ##5 ##7 ##8 ##: ##; ##= ##> #$@ #$# #$$ #$5 #$7 #$8 #$: #$; #$= #$> #5@ #5#

short num; char spec; struct heap *next; A; )**********************************************************) struct 9inary3ree 0 char *name; struct heap *line; struct 9inary3ree *left; struct 9inary3ree *right; A *tree = NUEE; )**********************************************************) )* EBSBE @ : main program *) )**********************************************************) main () 0 L EB *fp; char *filename(); struct 9inary3ree *Dlose<ata+truct(); printf (&2n dentifier Dross Reference S #.@2n2n&); if ((fp = fopen (filename()(&r&)) == NUEE) 0 printf (&Dan"t read file .. 1%ortedI2n2n&); exit(@); A DH = getc(fp); while (Ifeof(fp)) 0 +6ip9lan6s (fp); Record?ord (fp); A list <s (tree); Dlose<ata+truct(tree); printf (&2n'd lines in source file2n&(E NBDGUN3); A )**********************************************************) )* EBSBE # *) )**********************************************************) +6ip9lan6s (fp) L EB *fp; 0 while (Ifeof(fp)) )* +6ip irrele4ant characters *)

#5$ 0 #55 if (iscsymf(DH)) #57 0 #58 return(<UJJ\); #5: A #5; else #5= 0 #5> ,articular+6ip(fp); #7@ A #7# A #7$ A #75 #77 )**********************************************************) #78 #7: Record?ord (fp) )* get < in %uffer M tu%e it to data *) #7; #7= L EB *fp; #7> #8@ 0 int to6; #8# #8$ DopyNext < (fp); #85 #87 if ((to6 = to6en()) == @) )* if not res4ed word *) #88 0 #8: RecordUser <(isfunction(fp)); #8; A #8= #8> +,BD 1EDH1R = " "; #:@ A #:# #:$ )**********************************************************) #:5 #:7 list <s (p) )* Eist 9inary 3ree *) #:8 #:: struct 9inary3ree *p; #:; #:= 0 struct heap *h; #:> int i = @; #;@ #;# if (p I= NUEE) #;$ 0 #;5 list <s (p-/left); #;7 printf (&2n'-$@s&(p-/name); #;8 #;: for (h = p-/line; (h I= NUEE); h = h-/next) #;; 0 #;= printf (&'c'-8d&(h-/spec(h-/num); #;> if ((PPi ' =) == @) #=@ 0 #=# printf (&2n &); #=$ A #=5 A #=7 #=8 printf (&2n&); #=: list <s (p-/right); #=; A #== A #=> #>@ )*********************************************************)

#># #>$ struct 9inary3ree *Dlose<ata+truct (p) )* Recursi4eI *) #>5 #>7 struct 9inary3ree *p; #>8 #>: 0 #>; if (p-/left I= NUEE) #>= 0 #>> Dlose<ata+truct(p-/left); $@@ A $@# else if (p-/right I= NUEE) $@$ 0 $@5 Dlose<ata+truct(p-/right); $@7 A $@8 $@: deleteheap(p-/line); $@; releasetree(p); $@= return (NUEE); $@> A $#@ $## )*********************************************************) $#$ )* EBSBE $ *) $#5 )*********************************************************) $#7 $#8 ,articular+6ip (fp) )* handle particular characters *) $#: $#; L EB *fp; $#= $#> 0 char c; $$@ $$# switch (DH) $$$ $$5 0 $$7 case ")" : if ((c = getc(fp)) == "*") $$8 0 $$: s6ipcomment (fp); $$; A $$= else $$> 0 $5@ DH = c; $5# return (<UJJ\); $5$ A $55 %rea6; $57 $58 case "&" : if (s6iptochar (fp("&") / J1C+3R) $5: 0 $5; printf (&+tring too long or unterminated &); $5= printf (&at line 'd2n&(E NBDGUN3); $5> exit (@); $7@ A $7# %rea6; $7$ $75 case "2"": if (s6iptochar (fp("2"") == #) $77 0 $78 if (DH=="2"") DH = getc(fp);; $7: A $7; %rea6; $7= $7> case "-" : s6iptochar(fp(" ");

$8@ +,BD 1EDH1R = "-"; $8# %rea6; $8$ $85 case "2n": PPE NBDGUN3; $87 default : DH = getc(fp); $88 +,BD 1EDH1R = " "; $8: A $8; A $8= $8> )*********************************************************) $:@ $:# DopyNext < (fp) )* ,ut next identifier into 9ULLBR *) $:$ $:5 L EB *fp; $:7 $:8 0 int i = @; $:: $:; while (Ifeof(fp) MM (iscsym (DH))) $:= 0 $:> 9ULLBRXiPPY = DH; $;@ DH = getc (fp); $;# A $;$ $;5 9ULLBRXiY = "2@"; $;7 A $;8 $;: )**********************************************************) $;; $;= to6en () )* 3o6en: pos in ?GR<319EB *) $;> $=@ 0 int i; $=# $=$ for (i = @; i . ?GR<319EB; iPP) $=5 0 $=7 if (strcmp(M(9ULLBRX@Y)(?GR<319EBXiY) == @) $=8 0 $=: return(i); $=; A $== A $=> return(@); $>@ A $># $>$ )*********************************************************) $>5 $>7 RecordUser < (fnflag) )* chec6 < type M install data *) $>8 $>: int fnflag; $>; $>= 0 char *strcat(); $>> struct 9inary3ree *install(); 5@@ 5@# if (fnflag) 5@$ 0 5@5 strcat (9ULLBR(&()&); 5@7 tree = install (tree); 5@8 A 5@: else 5@; 0 5@= tree = install (tree);

5@> 5#@ 5## 5#$ 5#5 5#7 5#8 5#: 5#; 5#= 5#> 5$@ 5$# 5$$ 5$5 5$7 5$8 5$: 5$; 5$= 5$> 55@ 55# 55$ 555 557 558 55: 55; 55= 55> 57@ 57# 57$ 575 577 578 57: 57; 57= 57> 58@ 58# 58$ 585 587 588 58: 58; 58= 58> 5:@ 5:# 5:$ 5:5 5:7 5:8 5:: 5:;

)**********************************************************) isfunction (fp) L EB *fp; 0 while(Ifeof(fp)) 0 if (I(DH == " " QQ DH == "2n")) 0 %rea6; A else if (DH == "2n") 0 PPE NBDGUN3; A DH = getc(fp); A if (DH == "(") 0 return (3RUB); A else 0 return (L1E+B); A A )**********************************************************) deleteheap (h) struct heap *h; 0 struct heap *temp = h; while (hI=NUEE MM tempI=NUEE) 0 temp = h-/next; releaseheap(h); h = temp; A A )**********************************************************) )** EBSBE 5 **) )**********************************************************) s6ipcomment (fp) L EB *fp; 0 char cs = "x"; )* s6ip to char after comment *) )* Release %ac6 to free memory pool *) )* returns 3RUB if < is a fn *)

5:= for (DH = getc(fp); Ifeof(fp); DH = getc(fp)) 5:> 0 5;@ switch (DH) 5;# 0 5;$ case "2n": PPE NBDGUN3; 5;5 %rea6; 5;7 case ")" : if (cs == "*") 5;8 0 5;: DH = getc(fp); 5;; return(<UJJ\); 5;= A 5;> A 5=@ cs = DH; 5=# A 5=$ A 5=5 5=7 )*********************************************************) 5=8 5=: s6iptochar (fp(ch) )* s6ip to char after ch *) 5=; 5== L EB *fp; 5=> char ch; 5>@ 5># 0 int c=@; 5>$ 5>5 while (((DH =getc(fp)) I= ch) MM Ifeof(fp)) 5>7 0 5>8 if (DH == "2n") 5>: 0 5>; PPE NBDGUN3; 5>= A 5>> cPP; 7@@ A 7@# 7@$ DH = getc(fp); 7@5 return (c); 7@7 A 7@8 7@: )*********************************************************) 7@; 7@= struct 9inary3ree *install (p) )* install < in tree *) 7@> 7#@ struct 9inary3ree *p; 7## 7#$ 0 struct heap *pushonheap(); 7#5 struct 9inary3ree *newtree(); 7#7 char *stringin(); 7#8 int pos; 7#: 7#; if (p == NUEE) )* new word *) 7#= 0 7#> p = newtree(); 7$@ p-/name = stringin(9ULLBR); 7$# p-/line = pushonheap (NUEE); 7$$ p-/left = NUEE; 7$5 p-/right = NUEE; 7$7 return (p); 7$8 A 7$:

7$; 7$= 7$> 75@ 75# 75$ 755 757 758 75: 75; 75= 75> 77@ 77# 77$ 775 777 778 77: 77; 77= 77> 78@ 78# 78$ 785 787 788 78: 78; 78= 78> 7:@ 7:# 7:$ 7:5 7:7 7:8 7:: 7:; 7:= 7:> 7;@ 7;# 7;$ 7;5 7;7 7;8 7;: 7;; 7;= 7;> 7=@ 7=# 7=$ 7=5 7=7 7=8

if ((pos = strcmp (9ULLBR(p-/name)) == @) )* found word*) 0 p-/line = pushonheap(p-/line); return (p); A if (pos . @) 0 p-/left = install(p-/left); A else 0 p-/right = install(p-/right); A return (p); A )*********************************************************) )* EBSBE 7 *) )*********************************************************) struct heap *pushonheap (h) struct heap *h; 0 struct heap *hp(*newheap(); hp = newheap(); hp-/num = E NBDGUN3; hp-/spec = +,BD 1EDH1R; hp-/next = h; return (hp); A )*********************************************************) )* 3GGEW 3 file input *) )*********************************************************) %ac6one (ch(fp) char ch; L EB *fp; 0 if (ungetc(ch(fp) I= ch) 0 printf (&2n<e%ug: 3ool6it file input: %ac6one() L1 EB<2n&); exit(@); A A )**********************************************************) )* 3GGEW 3 stdin *) )**********************************************************) char *filename () )* %ac6space one in file *) )* push nxt ln no.to heap *) )* 3race down list *)

7=: 0 static char *fsp = &.................................&; 7=; 7== do 7=> 0 7>@ printf (&Bnter filename of source program: &); 7># scanf (&'55s&(fsp); 7>$ s6ipgar% (); 7>5 A 7>7 while (strlen(fsp) == @); 7>8 return (fsp); 7>: A 7>; 7>= )*********************************************************) 7>> 8@@ s6ipgar% () )* s6ip gar%age upto end of line *) 8@# 8@$ 0 8@5 while (getchar() I= "2n"); 8@7 A 8@8 8@: )**********************************************************) 8@; )* 3GGEW 3 data structure *) 8@= )**********************************************************) 8@> 8#@ char *stringin (array) )* cpy str in arry to ptr loc*) 8## 8#$ char *array; 8#5 8#7 0 char *malloc()(*ptr; 8#8 int i; 8#: 8#; ptr = malloc (strlen(array)P#); 8#= for (i = @; arrayXiY I= "2@"; ptrXiY = arrayXiPPY); 8#> ptrXiY = "2@"; 8$@ return(ptr); 8$# A 8$$ 8$5 )**********************************************************) 8$7 8$8 struct heap *newheap () 8$: 8$; 0 char *malloc (); 8$= return ((struct heap *) malloc(siNeof(struct heap))); 8$> A 85@ 85# )**********************************************************) 85$ 855 struct 9inary3ree *newtree () 857 858 0 char *malloc (); 85: return ((struct 9inary3ree *) malloc(siNeof(struct 9inary3ree))); 85; A 85= 85> )*********************************************************) 87@ 87# releaseheap (ptr) 87$ 875 struct heap *ptr;

877 878 0 87: if (free((char *) ptr) I= @) 87; 87= 0 87> printf (&3GGEW 3 datastruct: lin6 release failed2n&); 88@ A 88# A 88$ 885 )**********************************************************) 887 888 releasetree (ptr) 88: 88; struct 9inary3ree *ptr; 88= 88> 0 8:@ if (free((char *) ptr) I= @) 8:# 8:$ 0 8:5 printf (&3GGEW 3 datastruct: lin6 release failed2n&); 8:7 A 8:8 A 8:: )* end *) 8:; 8:=

+ut$ut of !ross )eferencer


dentifier Dross Reference S #.@ Bnter filename of source program: Dref.c 8:= 9ULLBR 9inary3ree $>> =$ DH 5:= $:> #55 Dlose<ata+truct() DopyNext <() L EB E NBDGUN3 #> NUEE $@# 7$5 #>; 7$$ #;: 7$# #;# 7#; #@$ 58@ => 58@ $@= #$: 7$; 88; #>7 7@$ 55$ $:; #@; $@5 $:# 7;@ >; 78: 7$@ 85: #>$ 5>8 5$> $87 $# #>> #8$ 5== 5>; 5:7 5;$ 5#: 5$; $:5 $85 $#; $5= #7= ##; 5@5 85: #:: 5>5 5$8 $78 #>$ $=7 855 >> 5=@ 5$# $78 ##: $;5 7#5 =: 5;: 5$# $5@ >> $:> 7#@ =8 5;@ $;@ $$# $@ 7@=

5:=

,articular+6ip() RecordUser <() Record?ord() +,BD 1EDH1R +6ip9lan6s() ?GR<319EB ?GR<319EB array %ac6one() c ch cs deleteheap() <UJJ\ exit() L1E+B feof() filename() fnflag fopen() fp 5=: 5$> $:# $$7 #5> #@;

$#8 $>7 #7: 78; #$7 $=7 $=$ 8#= 7:; 7@5 7;5 5=@ 577 5;; 7;: 55= 5>5 7=7 5@# #@$ 7;5 5;: 5#> $87 $#; #5@ #@$ 8:@ 7>8 $87 7@$ $78 8@5

#5> #8: ##$ $88 ### $= $= 8#= -#; 8#; 8#$ 8#@ $8@ #8> $$

5>> 7;5 5;7 $@: $5# $5> -#5 5:= #@$ $>:

5># 7:> 5::

$5@ 7:;

$$7 5>5

$#> 5=> 5=:

#58 #@8

-#7

5#> >= $>7

$:;

#5@

#@>

7;@ 5:= 5#: $7> $#8 #$: >; 87: 7>7 5>5 $$7

7:; 5:= 5#7 $78 #8: #$7

7@$ 5:= $;@ $75 #8$ ##$

5>5 5:7 $:; $58 #7= ###

5>5 5:$ $:5 $$: #7: #@>

5==

free() fsp getc() getchar()

7># 5;: #@;

7=: 5:= 5:= 5$> $;@

57= #;: 7#$

78= 57: #;: 875 57= 7:@

78# 577 #:= 8$= 57: 78= 8#= $=$ #:> 758

77> #;= 8$= #:= 78; 8#= $=$ 7@=

587 #;= 8$8 =7 78: 8#= $=@ 5@=

585 #;: 785 ;8 788 8#= $;5 5@7

58$ #;: 78# ;$ 785 8#8 $:> $>>

58@

heap

77>

hp i $=7 $:8

8#> $=$ #;> 75> $:; #55 5#7 758 7$> #=: >8 85: $@ $58 7$; 8$8 855 78= 78:

$=:

install() iscsym() iscsymf() isfunction() left line list <s() main() malloc() J1C <+ FB J1C+3R name newheap() newtree() next num p 7$> 7#> $@# #;7 pos printf() #=# ptr

#8: 758 7$> #;5 7$$ 7$# #:7 #>> $@: ##8 #>; #;: #;5 =7 =8

858 -#: -#8 7$@ 788 7#> 58$ #;= 75> 7$7 7#@ #>; #;# 7$; 87> #;7 88;

8$=

8$;

8#;

8#7

#;7 785 7#5 #;: ;5 75> 7$5 7@= #>7 #:: 7#8 7>@ ##; 888

=5

;8

77$ 7$; 7#; #>> #;5 755 8:5 #;= 8:@

758 7$$ $@; #>$ #:7

758 7$# $@: #=:

75@ 7$@ $@5 #;:

7$>

7;8 #@7 87:

$5= #@# 875

$5; 87#

#=8 8$@

8#> pushonheap() releaseheap() releasetree() right scanf() s6ipcomment() s6ipgar%() s6iptochar() spec strcat() strcmp() stringin() strlen() temp to6 to6en() tree 3RUB ungetc()

8#= 77> 87# 888 75> 7># 5:$ 8@@ 5=: 78; 5@5 7$; 8#@ 8#; 587 #87 $;= 5@= 557 7;5

8#; 7$> 585 $@; 75>

8#7 7$# 7#$

7$5

$@5

$@#

#=:

=:

$$: 7>$ $7> #;= $>= $=7 7$@ 7>7 58$ #8@ #87 5@= -#$ 5@7 5@7 ##: ##8 => 58@ 57= 7#7 $75 ;7 $58

8:= lines in source file

!o##ents
This simplified program could ,e improved in a num,er of wa#s. 7ere are some suggestions for improvement

The program could determine whether an identifier was of t#pe pointer or not and, if so, la,el the line num,er with a N, e.g. N%"G G " N%"G 5t present the program onl# mar*s macros with a [ s#m,ol on the line at which the# are defined. .t could ,e made to mar* them at ever# line, so that [undef;ined s#m,ols and varia,les were clearl# distinguished.

%rrors and de ugging


.istakes> 6e,ugging can ,e a difficult process. .n man# cases compiler errors are not generated ,ecause the actual error which was present ,ut ,ecause the compiler got out of step. 1ften the error messages give a completel# misleading impression of what has gone wrong. .t is useful therefore to ,uild a list of errors and pro,a,le causes personall#. These few examples here should help ,eginners get started and perhaps give some insight into the wa# C wor*s.

Compiler Trappa,le Errors/un time errorsTracing errorsPathological Pro,lemsPorting Programs ,etween computers>u-

!o#$iler "ra$$a le %rrors


)issing semicolon@)issing ,race)ist#ping Upper Lower Case)issing inv comma3aria,le not declared or scope wrongUsing a function or assignment inside a macro2orgetting to declare a function which is not t#pe intT#pe mismatch in expressions-

Missing se#icolon?
5 missing semicolon is easil# trapped ,# the compiler. Ever# statement must end with a semi colon. 5 compound statement which is held in curl# ,races seldom needs a semi colon to follow.
statement; %ut: 0 A; .-- 3his semi colon is only needed if the curly %races enclose a type declaration or an initialiNer for static array)structure etc.

Missing closing race &


This error is harder to spot and ma# cause a whole host of irrelevant and incorrect errors after the missing ,race. Count ,races carefull#. 1ne wa# to avoid this is to alwa#s fill ,races in ,efore the statements are written inside them. 4o write

0 A

and fill in the statements afterwards. 1ften this error will generate a message li*e Iunexpected end of file9 ,ecause it is particularl# difficult for a compiler to diagnose.

Mist,$ing &$$er:Lower !ase


C distinguishes ,etween small and capital letters. .f a program fails at the lin*ing stage ,ecause it has found a reference to a function which had not ,een defined, this is often the cause.

Missing @uote '


.f a 8uote is missed out of a statement containing a string then the compiler will usuall# signal this with a message li*e+tring too long or unterminated.

0aria le not declared or sco$e wrong


This means that a varia,le is used which has not first ,een declared, or that a varia,le is used outside of its sealed capsule.

&sing a function or assign#ent inside a #acro


.f a%s (x) is a macro and not a function then the following are incorrecta%s (function()); a%s (x = function());

1nl# a single varia,le can ,e su,stituted into a macro. This error might generate something li*e Dlvalue re8uiredD.

-orgetting to declare a function which is not t,$e int


5ll functions return values of int ,# default. .f it is re8uired that the# return another t#pe of varia,le, this must ,# declared in two places- aC in the function which calls the new function, along with the other declarationsDallLunction () 0 char ch( function#()( *function$(); A

The function#() is t#pe char@ function$() is t#pe pointer to char. This must also ,e declared where the function is definedchar function# () 0 A

and
char *function$() 0 A

This error might result in the message Dt#pe mismatchD or Dexternal varia,leEfunction t#peEattri,ute mismatchD

",$e #is#atch in e*$ressions


There is a rule in C that all maths operations have to ,e performed with long varia,les. These are
int long int dou%le long float

The result is also a long t#pe. .f the user forgets this and tries to use short C automaticall# converts it into long form. The result cannot therefore ,e assigned to a short t#pe afterwards or the compiler will complain that there is a t#pe mismatch. 4o the following is wrongshort i(U = $; i = U * $;

.f a short result is re8uired, the cast operator has to ,e used to cast the long result to ,e a short one.
short i(U = $; i = (short) U * $;

%rrors not tra$$a le , a co#$iler <run ti#e errors=


Confusion of Q and QQ)issing 0 in scanf-

Confusing CRR and RRCUnwarranted assumptions a,out storage of arra#sEstructuresNum,er of actual and formal parameters does not matchConversion string in scanf or printf wrong5ccidental confusion of int short and char5rra#s out of ,ounds)athematical ErrorUncoordinated 1utput using putEget .E1Glo,al 3aria,les and /ecursion-

!onfusion of = and ==
5 statement such asif (a = @) 0 A

is valid C, ,ut notice that = is the assignment operator and not the e8ualit# operator ==. .t is legal to put an assignment inside the if statement Bor an# other functionC and the value of the assignment is the value ,eing assigned: 4o writing the a,ove would alwa#s give the result Aero Bwhich is I25L4E9 in CC so the contents of the ,races 0A would never ,e executed. To compare a to Aero the correct s#ntax isif (a == @) 0 A

Missing & in scanf


This error can often ,e trapped ,# a compiler, ,ut not in all cases. The arguments of the scanf statement must ,e pointers or addresses of varia,les, not the contents of the varia,les themselves. Thus the following is wrongint i; char ch; scanf (&'c 'd&(ch(i);

and should readint i; char; scanf (&'c 'd&( Mch( Mi);

Notice however that the M is not alwa#s needed if the identifier in the expression is alread# a pointer. The following is correctint *i; char *ch; scanf (&'c 'd&( ch( i);

.ncluding the M now would ,e wrong. .f this error is trappa,le then it will ,e something li*e D3aria,le is not a pointerD.

!onfusing !AA and AA!


.n man# cases these two forms are identical. 7owever, if the# are hidden inside another statement e.g.
array XDPPY = @;

then there is a su,tle difference. PPD causes D to ,e incremented ,# % ,efore the assignment ta*es place whereas DPP causes D to ,e incremented ,# % after the assignment has ta*en place. 4o if #ou find that a program is out of step ,# %, this could ,e the cause.

&nwarranted assu#$tions a out storage


C stores arra#s in rows, and as far as the language is concerned the storage locations are next to one another in one place up to the end of the arra#. This might not ,e exactl# true, in general. 5 program will ,e loaded into one or more areas Bwhere ever the operating s#stem can find spaceC and new varia,le space will ,e found wherever it is availa,le, ,ut this will not generall# ,e in whole ,loc*s Iside ,# side9 in the memor#. The following sort of construction onl# wor*s for simple data t#peschar arrayX#@Y; *array = @; *(array P #) = @; ... *(array P #@) = @;

<hile it is true that the varia,le Darra#D used without its s8uare ,rac*ets is a pointer to the first element of the arra#, it is not necessaril# true that the arra# will necessaril# ,e stored in this wa#. Usingchar arrayX#@Y; arrayX@Y = @; arrayX#Y = @; ... arrayX#@Y = @;

is safe. <hen finding a pointer to, sa#, the third element, #ou should not assume that
array P 5 * siNeof (datatype)

will ,e the location. UseM(arrayX5Y)

6o not assume that the siAe of a structure is the sum of the siAes of its parts: There ma# ,e extra data inside for operating s#stem use or for implementation reasons, li*e aligning varia,les with particular addresses.

"he nu# er of actual and for#al $ara#eters does not #atch


This pro,lem can ,e avoided in 5N4. C and CRR ,ut not in K0/ C. <hen passing values to a function the compiler will not spot whether #ou have the wrong num,er of parameters in a statement, provided the# are all of the correct t#pe. The values which are assumed for missing parameters cannot ,e guaranteed. The# are pro,a,l# gar,age and will most li*el# spoil a program.

"he conversion string in scanf:printf is wrong


.ncorrect .E1 is can ,e the result of poorl# matched conversion strings in .E1 statements. These are wrongfloat x; scanf (&'d&(Mx); should be float x; scanf (&'f&(Mx);

or evendou%le x; scanf (&'f&(Mx); should perhaps be float x; scanf(&'ld&(Mx);

5nother effect which can occur if the conversion specifier is selected as ,eing long when it the varia,le is reall# short is that neigh,ouring varia,les can receive the scanf values instead: 2or instance if two varia,les of the same t#pe happen to ,e stored next to each other in the memor#short i(U;

which might loo* li*e-------------------------------------Q Q Q --------------------------------------

and the user tries to read into one with a long int value, scanf will store a long int value, which is the siAe of two of these short varia,les. 4uppose the left hand ,ox were i and the right hand ,ox were U and #ou wanted to input the value of i- instead of gettingQ -------------------@@$578 Q Q -------------------i scanf U

might store

@@@@@@@@@@@@@@@$578

as
-----------------------Q @@@@@@@@@ Q @@@@@@$578 Q -----------------------i U

,ecause the value was long, ,ut this would mean that the num,er would over flow out of i into U and in fact U might get the correct value and i would ,e set to Aero:: Chec* the conversion specifiers::

3ccidental confusion of int, short and char


1ften when wor*ing with characters one also wants to *now their 54C.. values. .f charactersEintegers are passed as parameters it is eas# to mist#pe char for int etc.. The compiler pro,a,l# won9t notice this ,ecause no conversion is needed ,etween int and char. Characters are stored ,# their 54C.. values. 1n the other hand if the declaration is wrongfunction (ch) int (ch); 0 A

,ut the character is continuall# assumed to ,e a character ,# the program, a crashworth# routine might ,e the result.

3rra,s out of ounds


C does not chec* the limits of arra#s. .f an arra# is siAed-

type arrayX8Y;

and the #ou allow the program to write to arrayX:Y or more, C will not complain. 7owever the computer might: .n the worst case this could cause the program to crash.

Mathe#atical %rror
C does not necessaril# signal mathematical errors. 5 program might continue regardless of the fact that a mathematical function failed. 4ome mathematical errors Boften su,tle onesC can ,e caused ,# forgetting to include to file math.h at the start of the program.

&ncoordinated +ut$ut using uffered I:+


1utput which is generated ,# functions li*e putchar(), puts() is ,uffered. This means that it is not written to the screen until the ,uffer is either full or is specificall# emptied. This results in strange effects such as programs which produce no output until all the input is complete Bshort programsC or spontaneous ,ursts of output at uncoordinated intervals. 1ne cure is to terminate with a newline 2n character which flushes the ,uffers on each write operation. 4pecial functions on some s#stems such as getch() ma# also suffer from this pro,lem. 5gain the cure is to writeprintf (&2n&);

ch Q getchBC@

5lo al 0aria les and )ecursion


Glo,al varia,les and recursion should not ,e mixed. )ost recursive routines wor* onl# ,ecause the# are sealed capsules and what goes on inside them can never affect the outside world. The onl# time that recursive functions should alter glo,al storage is when the function concerned operates on a glo,al data structure. Consider a recursive functionint REG91E; recursion () 0 if (PPREG91E == @) 0 return (@); A alterREG91E(); recursion(); A )* another function which alters REG91E *)

This function is treading a fine line ,etween safet# and digging its own recursive grave. 5ll it would ta*e to crash the program, would ,e the careless use of REG91E in the function alterREG91E() and the function would never ,e a,le to return. The stac* would fill up the memor# and the program would plunge down an unending recursive well.

"racing %rrors
Locating a pro,lem-

Locating a $ro le#


Complex ,ugs can ,e difficult to locate. 7ere are some tips for fault finding%. Tr# to use local varia,les, in preference to glo,al ones for local duties. Never rel# on glo,al varia,les for passing messages ,etween functions. ". Chec* varia,le declarations and missing parameters. G. Chec* that a program has not run out of private memor#. B.f it repeatedl# crashes for no apparent reason, this could ,e a cause.C )a*e the program stac* siAe ,igger if that is possi,le. . Use statements li*e printfBDprogram is now hereDC to map out the progress of a program and to chec* that all function calls are made correctl#. H. Use statements li*e ch Q getcharBC to halt a program in certain places and to find out the exact location at which things go wrong. M. Tr# Dcommenting outD lines of suspect code. .n other words- put comment mar*ers around lines that #ou would li*e to eliminate temporaril# and then recompile to pinpoint errors. (. Chec* that the compiler dis* has not ,een corrupted Bma*e a new cop#C ; getting desperate now: '. Tr# ret#ping the program, or using a filter which strips out an# illegal characters which might have found their wa# into a program. &. Get some sleep: 7ope the pro,lem has gone awa# in the morning. 2ailing these measures, tr# to find someone who programs in C regularl# on the computer s#stem concerned.

Pathological Pro le#s


Pro,lems which def# reasona,le explanations are called pathological or Isic*9. 4ometimes these will ,e the result of misconceptions a,out C functions, ,ut occasionall# the# ma# ,e the result of compiler ,ugs, or operating s#stem design peculiarities. Consider the following example which was encountered while writing the simple example in the chapter on 2iles and 6evices, su,section ILow Level 2ile 7andling9- in that program a seemingl# innocent macro defined ,#
-define DER+DRN() putchar("2f");

caused the C li,rar# functions creat() and remo4e() to fail is remar*a,le wa#s on an earl# 5miga C compiler: The pro,lem was that a single call to DER+DRN() at the start of the function <elLile() caused ,oth of the li,rar# functions Bin ver# different parts of the programC a,ove to ma*e recursing function calls the function <elLile(). The deletion of DER+DRN() cured the pro,lem entirel#: .n general it is worth chec*ing carefull# the

names of all functions within a program to ,e sure that the# do not infringe upon li,rar# functions. 2or example, read() and write() are names which ever#one wishes to use at some point, ,ut the# are the names of standard li,rar# functions, so the# ma# not ,e used. Even capitaliAing B/eadBC E <riteBCC might not wor*- ,eware that special operating s#stem li,raries have not alread# reserved these words as li,rar# commands. .t is almost impossi,le to advise a,out these errors. 5 programmer can onl# hope to tr# to eliminate all possi,ilities in homing in on the pro,lem. To mis8uote 4herloc* 7olmesD5t the end of the da#, when all else fails and the manuals are in the waste paper ,as*et, the last possi,ilit#, however impro,a,le, has to ,e the truth.D

Porting Progra#s etween co#$uters


Programs written according to the st#le guidelines descri,ed in this ,oo* should ,e highl# porta,le. Nevertheless, there are almost inevita,l# pro,lems in porting programs from one computer to another. The most li*el# area of incompati,ilit# ,etwee compilers regards filing operations, especiall# scanf(). Programmers attempting to transfer programs ,etween machines are recommended to loo* at all the scanf() statements first and to chec* all the conversion specifiers with a local compiler manual. scanf() is capa,le of producing a full spectrum of weird effects which have nothing to do with .E1. 7ere are some more potential pro,lems to loo* out for

5ssumptions a,out the siAe of data o,?ects such as int and float can ,e ris*#. Chec* conversion characters in printf() and scanf() as some compilers choose slightl# different conventions for these. The stac* siAe for Bmemor# availa,le toC a program is li*el# to var# ,etween s#stems. This can cause errors at run time if a program runs out of space, even though there is nothing wrong with the code. Chec* for functions which rel# on the speed of a particular computer. 2or example, pauseBC or wait loops. 4ome computers ma# scarcel# notice counting to H!!!!, whereas others ma# la,our at it for some time:

Chec* for assumptions made a,out filenames. e.g. limitedEunlimited siAe, valid characters etc..

(uestions
4pot the errors in the following#. $. 5. 7. 8. :. ;. =. function (string(i) 0 char *string; int i; A

&.

#@.while (a . %)

##. #$. #5. #7. #8. #:.

0 while (% == @) 0 printf (&a is negati4e&); A

%(.
#=.struct Name #>. 0 $@. int mem%er#; $#. int mem%er$; $$. A $5.

/u##ar, of !

/eservedPreprocessor 6irectives7eader 2iles and Li,rariesConstantsPrimitive 6ata T#pes4torage Classes.dentifiers4tatementsCharacter Utilities4pecial Control Characters.nputE1utput 2unctionsprint conversionsscanf conversions)aths Li,rar# 4ummar#goto-

)eserved 1ords
auto

storage class specifier BdeclarationC


%rea6 case char continue default do dou%le

statement Bescape from switch or loopC option prefix within switch statement t#pename statement B,ranch to start of next loopC option in switch statement statement t#pename

else entry extern float for goto if int long register return short siNeof static struct switch

statement Breserved for the future useC storage class specifier t#pename statement goto la,el statement t#pename t#pename storage class specifier functional statement t#pename compile time operator storage class specifier partial t#pename statement

typedef union

statement partial t#pename

unsigned while enum 4oid const signed

t#pename statement partial t#pename- ordinal t#pes onl# t#pename storage class specifierBno storage allocatedC t#pename

4olatile

storage class specifier

Pre$rocessor 'irectives

-include -define -undef -if -ifdef -ifndef -else -endif -line -error

include file for lin*ing define a preprocessor s#m,olEmacro un;define a previousl# defnined s#m,ol test for conditional compilation BdittoC BdittoC BdittoC BdittoC de,ug tool de,ug tool

Header -iles and Li raries


7eader files contain macro definitions, t#pe definitions and varia,leE function declarations which are used in connection with standard li,raries. The# supplement the o,?ect code li,raries which are lin*ed at compile time for standard li,rar# functions. 4ome li,rar# facilities are not availa,le unless header files are included. T#pical names for header files arestdio.h ctype.h math.h

4tandard .E1 Bli,cC. )acro for character t#pes. )athematical definitions Bli,mC

!onstants
#nteger Characters !..& onl# 1ctal Prefix ! BAeroC chars !..( onl# -e%adeci$al Prefix !x BAero exC chars a..f 5..f !..& (%plicit 8ong .ntegerE1ctal or 7exadecimal t#pes can ,e declared long ,# writing L immediatel# after the constant. *haracter 6eclared in single 8uotes e.g. "x" "2n" 3loat

Characters !..! and one D.D )a# also use scientific notation exponents with e or B preceding them. e.g. $.#7B#$ 5.$e-$ Strings 4tring constants are written in dou,le 8uotes e.g. &3his is a string& and have t#pe pointer to character.

Pri#itive 'ata ",$es


char int

7olds an# character .nteger t#pe

short int long int float long float dou%le 4oid

.nteger no larger than int .nteger no smaller than int 2loating point Breal num,erC 6ou,le precision float BdittoC 7olds no value, uses no storage Bexcept as a pointerC

/torage !lasses
auto const extern static

Local varia,le Bredundant *e#wordC No varia,le allocated, value doesn9t change 3aria,le is defined in another file 3alue is preserved ,etween function calls

register 4olatile

4tored in a register, if possi,le 3alue can ,e changed ,# agents outside the program.

Identifiers
.denitifiers ma# contain the characters- @..>, 1..F, a..N and K Bthe underscore characterC. .dentifiers ma# not ,egin with a num,er. BThe compiler assumes that an o,?ect ,eginning with a num,er is a num,er.C

/tate#ents
5 single statement is an# valid string in C which ends with a semi colon. e.g.

a = :; printf (&

lo4e D %ecause...&);

5 compound statement is an# num,er of single statements groued together in curl# ,races. The curl# ,races do not end with a semi colon and stand in place of a single statement. 5n# pair of curl# ,races ma# contain local declarations after the opening ,race. e.g.
0 a = :; A 0 int a; a = :; printf (& A lo4e D %ecause...&);

4ummar# of 1perators and Precedence The highest priorit# operators are listed first.
"perator () XY PP -(type) * M [ I * ) ' P // .. / /= .= . == I= M "peration parentheses sOuare %rac6ets increment decrement cast operator the contents of the address of unary minus one"s complement logical NG3 multiply di4ide remainder (JG<) add su%tract shift right shift left is greater than greater than or eOual to less than or eOual to less than is eOual to is not eOual to %itwise 1N< Evaluated left to right left to right right right right right right right right right to to to to to to to to left left left left left left left left

left to right left to right left to right left to right left to right left to right left to right left left left left to to to to right right right right

left to right left to right left to right

Z Q MM QQ = P= -= *= )= '= //= ..= M= Z= Q=

%itwise %itwsie logical logical

exclusi4e GR includi4e GR 1N< GR

left left left left right right right right right right right right right right right

to to to to to to to to to to to to to to to

right right right right left left left left left left left left left left left

assign add assign su%tract assign multiply assign di4ide assign remainder assign right shift assign left shift assign 1N< assign exclusi4e GR assign inclusi4e GR assign

!haracter &tilities
char ch; isalpha(ch) isupper(ch) islower(ch) isdigit(ch)

.s alpha,etic a..A 5..L .s upper case .s lower case .s in the range !..&

isxdigit(ch) isspace(ch) ispunct(ch) isalnum(ch) isprint(ch) isgraph(ch) iscntrl(ch) isascii(ch) iscsym(ch) toupper(ch) tolower(ch) toascii(ch)

.s !..& or a..f or 5..2 .s white space character BspaceEnewlineEta,C .s punctuation or s#m,olic .s alphanumeric Balphavetic or num,erC .s printa,le on the screen Band spaceC .f the character is printa,le Bnot spaceC .s a control character Bnot printa,leC .s in the range !..%"( .s a valid character for a C identifier Converts character to upper case Converts character to lower case Converts character to ascii Bmas*s off top ,itC

/$ecial !ontrol !haracters


Control characters are invisi,le on the screen. The# have special purposes usuall# to do with cursor movement and are written into an ordinar# string or character ,# t#ping a ,ac*slash character P followed ,# some other character. These characters are listed ,elow.
2% 2f 2n 2r 2t 24 2& 2" 22 2ddd

,ac*space +4 form feed 22 Balso clear screenC new line NL Bli*e pressing returnC carriage return C/ Bcursor to start of lineC horiAontal ta, 7T vertical ta, Bnot all versionsC dou,le 8uotes Bnot all versionsC single 8uote character 9 ,ac*slash character P character ddd where ddd is an 54C.. code given in octal or ,ase '. B4ee 5ppendix CC

In$ut:+ut$ut -unctions
printf () scanf ()

2ormatted printing 2ormatted input anal#sis

getchar() putchar() gets () puts ()

Get one character from stdin file ,uffer Put one charcter in stdout file ,uffer Get a string from stdin Put a string in stdout

fprintf() fscanf() fgets() fputs() fopen()

2ormatted printing to general files 2ormatted input from general files Get a string from a file Put a string in a file

1penEcreate a file for high level access


fclose() getc()

Close a file opened ,# fopenBC Get one character from a file BmacroFC

ungetc(); putc()

Undo last get operation Put a character to a file BmacroFC

fgetc() fputc() feof() fread()

Get a character from a file BfunctionC Put a character from a file BfunctionC End of file . returns true or false /ead a ,loc* of characters

fwrite() ftell() fsee6() rewind() fflush() open()

<rite a ,loc* of characters /eturns file position 2inds a file position )oves file position to the start of file Empties file ,uffers 1pen a file for low level use

close() creat() read() write()

Close a file opened with openBC Create a new file /ead a ,loc* of untranslated ,#tes <rite a ,loc* of untranslated ,#tes

rename() unlin6() remo4e() lsee6()

/ename a file 6elete a file 6elete a file 2ind file position

printf d u

conversion s$ecifiers
signed denar# integer Unsigned denar# integer

x o s c f e g

7exadecimal integer 1ctal integer 4tring 4ingle character 2ixed decimal floating point 4cientific notation floating point

Use f or e, whichever is shorter The letter l BellC can ,e prefixed ,efore these for long t#pes.
scanf

conversion s$ecifers

The conversion characters for scanf are not identical to those for printf and it is important to distinguish the long t#pes here.
d

6enar# integer
ld x o h f lf e le c s

Long int 7exadecimal integer 1ctal integer 4hort integer 2loat t#pe Long float or dou,le 2loat t#pe 6ou,le 4ingle character Character string

Maths Li rar,
These functions re8uire dou,le parameters and return dou,le values unless otherwise stated. .t is important to include math.h.
19+(x)

/eturn a,solute BunsignedC value. BmacroC

fa%s(x) ceil(x)

/eturn a,solute BunsignedC value. B2unctionC /ounds up a Ddou,leD varia,le

floor(x) exp(x) log(x) log#@(x) pow(x(y) sOrt(x) sin(x) cos(x) tan(x) asin(x) acos(x) atan(x)

/ounds down BtruncatesC a Ddou,leD varia,le. 2ind exponent 2ind natural logarithm 2ind logarithm to ,ase %! /aise x to the power # 48uare root 4ine of Bx in radiansC Cosine of Bx in radiansC Tangent of Bx in radiansC .nverse sine of x in radians .nverse cosine of x in radians .nverse tangent of x in radians

atan$(x(y) sinh(x) cosh(x) tanh(x)

.nverse tangent of x)y in radians 7#per,olic sine 7#per,olic cosine 7#per,olic tangent

goto

This word is redundant in C and encourages poor programming st#le. 2or this reason it has ,een ignored in this ,oo*. 2or completeness, and for those who insist on using it Bma# their programs recover gracefull#C the form of the goto statement is as followsgoto la%el;

is an identifier which occurs somewhere else in the given function and is defined as a la,el ,# using the colonla%el la%el : printf (&UghI \ou used a gotoI&);

3ll the )eserved 1ords


7ere is a list of all the reserved words in C. The set of reserved words a,ove is used to ,uild up the ,asic instructions of C@ #ou can not use them in programs #our write Please note that this list is somewhat misleading. )an# more words are out of ,ounds. This is ,ecause most of the facilities which C offers are in li,raries that are included in programs. 1nce a li,rar# has ,een included in a program, its functions are defined and #ou cannot use their names #ourself. C re8uires all of these reserved words to ,e in lower case. BThis does mean that, t#ped in upper case, the reserved words could ,e used as varia,le names, ,ut this is not recommended.C B5 DdD ,# the word implies that it is used as part of a declaration.C
auto d %rea6 case char d continue default do dou%le d else entry extern d float d for goto if int d long d register d return short d siNeof static d struct switch typedef d union d unsigned d while

also in modern implementations. enum d 4oid d const d signed d 4olatile d

"hree Languages4 1ords and /,# ols !o#$ared


.f #ou are alread# familiar with Pascal B5lgol..etcC or ++C +54.C, the following ta,le will give #ou a rough and read# indication of how the main words and s#m,ols of the three languages relate.
D = ,ascal := 91+ D =

== *() )(' printf (&..&); scanf (&..&(a); for (x = ..;...;) 0 A while (..) 0 A do 0 A while (..); N)1 if (..) ..; else ...; switch (..) 0 case : A )* .... *) * struct union

= *() di4( mod writeln (".."); write (".."); readln (a); read (a); for x := ...to %egin end; while ...do %egin end; N)1

= *() < S( JG< ,R N3 &..& N,U3 a LGR x = ... NBC3 x N)1

N)1

repeat until (..) if ... then ... else ....; case .. of end; 0 ..... A Z record N)1 if and switch

RB,B13 UN3 E .. L .. 3HBN.. BE+B N)1

RBJ ..... V I T N)1 N)1

The conditional expressions are essentiall# identical to Pascal9s own words if and case ,ut there is no redundant DthenD. +54.C has no analogue of the switch construction. The loop constructions of C are far superior to those of either +54.C or Pascal however. .nput and 1utput in C is more flexi,le than Pascal, though correspondingl# less ro,ust in terms of program crasha,ilit#. .nput and 1utput in C can match all of +54.Cs string operations and provide more, though string varia,les can ,e more aw*ward to deal with.

!haracter !onversion "a le


This ta,le lists the decimal, octal, and hexadecimal num,ers for characters ! ; %"(.
<ecimal @ # $ 5 7 8 : ; = > #@ ## #$ #5 #7 #8 #: #; #= #> $@ $# $$ $5 $7 $8 $: $; $= $> 5@ 5# 5$ 55 57 58 5: 5; 5= 5> 7@ 7# 7$ 75 77 78 7: 7; 7= 7> 8@ Gctal @ # $ 5 7 8 : ; #@ ## #$ #5 #7 #8 #: #; $@ $# $$ $5 $7 $8 $: $; 5@ 5# 5$ 55 57 58 5: 5; 7@ 7# 7$ 75 77 78 7: 7; 8@ 8# 8$ 85 87 88 8: 8; :@ :# :$ Hexadecimal @ # $ 5 7 8 : ; = > 1 9 D < B L #@ ## #$ #5 #7 #8 #: #; #= #> #1 #9 #D #< #B #L $@ $# $$ $5 $7 $8 $: $; $= $> $1 $9 $D $< $B $L 5@ 5# 5$ Dharacter D3RE-_ D3RE-1 D3RE-9 D3RE-D D3RE-< D3RE-B D3RE-L D3RE-R D3RE-H D3RED3RE-^ D3RE-W D3RE-E D3RE-J D3RE-N D3RE-G D3RE-, D3RE-] D3RE-R D3RE-+ D3RE-3 D3RE-U D3RE-S D3RE-? D3RE-C D3RE-\ D3RE-F D3RE-X D3RE-2 D3RE-Y D3RE-Z D3RE-K I & T ' M " ( ) * P ( . ) @ # $

8# 8$ 85 87 88 8: 8; 8= 8> :@ :# :$ :5 :7 :8 :: :; := :> ;@ ;# ;$ ;5 ;7 ;8 ;: ;; ;= ;> =@ =# =$ =5 =7 =8 =: =; == => >@ ># >$ >5 >7 >8 >: >; >= >> #@@ #@# #@$ #@5 #@7 #@8 #@: #@; #@= #@>

:5 :7 :8 :: :; ;@ ;# ;$ ;5 ;7 ;8 ;: ;; #@@ #@# #@$ #@5 #@7 #@8 #@: #@; ##@ ### ##$ ##5 ##7 ##8 ##: ##; #$@ #$# #$$ #$5 #$7 #$8 #$: #$; #5@ #5# #5$ #55 #57 #58 #5: #5; #7@ #7# #7$ #75 #77 #78 #7: #7; #8@ #8# #8$ #85 #87 #88

55 57 58 5: 5; 5= 5> 51 59 5D 5< 5B 5L 7@ 7# 7$ 75 77 78 7: 7; 7= 7> 71 79 7D 7< 7B 7L 8@ 8# 8$ 85 87 88 8: 8; 8= 8> 81 89 8D 8< 8B 8L :@ :# :$ :5 :7 :8 :: :; := :> :1 :9 :D :<

5 7 8 : ; = > : ; . = / V _ 1 9 D < B L R H ^ W E J N G , ] R + 3 U S ? C \ F X 2 Y Z K ! a % c d e f g h i U 6 l m

##@ ### ##$ ##5 ##7 ##8 ##: ##; ##= ##> #$@ #$# #$$ #$5 #$7 #$8 #$: #$;

#8: #8; #:@ #:# #:$ #:5 #:7 #:8 #:: #:; #;@ #;# #;$ #;5 #;7 #;8 #;: #;;

:B :L ;@ ;# ;$ ;5 ;7 ;8 ;: ;; ;= ;> ;1 ;9 ;D ;< ;B ;L

n o p O r s t u 4 w x y N 0 Q A [ <BE

%#acs st,le file


The programming st#le used in this ,oo* can ,e taught to Emacs with the following site; lisp file;;; ;;; D( perl and DPP indentation( 9urgess style. (3homas +e4aldrud) ;;; (defconst %urgess-c-style "((c-ta%-always-indent (c-hanging-%races-alist (c-hanging-colons-alist . t) . ((su%statement-open %efore after) (%race-list-open))) . ((mem%er-init-intro %efore) (inher-intro) (case-la%el after) (la%el after) (access-la%el after))) . (scope-operator)) . ((arglist-close . c-lineup(defun-%loc6-intro (su%statement-open (statement-%loc6-intro (topmost-intro (case-la%el (%loc6-open (6nr-argdecl-intro ;(c-echo-syntactic-information-p . t) ) &9urgess ,rogramming +tyle&) ;; DustomiNations for all of c-mode( cPP-mode( and o%Uc-mode (defun %urgess-c-mode-common-hoo6 () ;; add my personal style and set it for the current %uffer (c-add-style &9URRB++& %urgess-c-style t) . . . . . . . #) 5) @) -#) @) @) -)))

(c-cleanup-list (c-offsets-alist arglist)

;; offset customiNations not in %urgess-c-style (c-set-offset "mem%er-init-intro "PP) ;; other customiNations ;; 6ey%indings for D( DPP( and G%Uecti4e-D. ?e can put these in ;; c-mode-map %ecause cPP-mode-map and o%Uc-mode-map inherit it (define-6ey c-mode-map &2D-m& "newline-and-indent) ) (add-hoo6 "c-mode-common-hoo6 "%urgess-c-mode-common-hoo6)

;;; ;;; Eite hac6 for ` slippe ` s6ri4e inn 6ompilerings6ommandoen i c( ;;; (h4is i66e Ja6file e6sisterer) ;;; samt en fancy heading h4is det er en ny fil. ;;; (add-hoo6 "c-mode-hoo6 (lam%da () ; (local-set-6ey &2D-c2D-c& "compile) (cond ((not (file-exists-p (%uffer-file-name))) (insert-string (concat &)*& (ma6e-string ;8 V*) &*)2n& &)*& (ma6e-string ;8 V ) &*)2n& (format &)* Lile: '-:;s *)2n& (%uffer-name)) &)*& (ma6e-string ;8 V ) &*)2n& (format &)* Dreated: '-:7s *)2n& (currenttime-string)) &)*& (ma6e-string ;8 V ) &*)2n& &)* 1uthor: / *)2n& &)*& (ma6e-string ;8 V ) &*)2n& &)* Re4ision: T dT *)2n& &)*& (ma6e-string ;8 V ) &*)2n& &)* <escription: *)2n& &)*& (ma6e-string ;8 V ) &*)2n& &)*& (ma6e-string ;8 V*) &*)2n& &2n-include .stdio.h/2n&)))) (outline-minor-mode #) (or (file-exists-p &ma6efile&) (file-exists-p &Ja6efile&) (set (ma6e-local-4aria%le "compile-command) (concat &gcc -o & (su%string (file-name-nondirectory %uffer-file-name) @ (string-match &22.cT& (file-name-nondirectory %uffer-filename))) & & (file-name-nondirectory %uffer-filename)))))) ;;; ;;; +amme for DPP

(add-hoo6 "cPP-mode-hoo6 (lam%da () ; (local-set-6ey &2D-c2D-c& "compile) (cond ((not (file-exists-p (%uffer-file-name))) (insert-string (concat &)*& (ma6e-string ;8 V=) &*)2n& &)*& (ma6e-string ;8 V ) &*)2n& (format &)* Lile: '-:;s *)2n& (%uffer-name)) &)*& (ma6e-string ;8 V ) &*)2n& (format &)* Dreated: '-:7s *)2n& (currenttime-string)) &)*& (ma6e-string ;8 V ) &*)2n& &)* 1uthor: *)2n& &)*& (ma6e-string ;8 V ) &*)2n& &)* Re4ision: T dT *)2n& &)*& (ma6e-string ;8 V ) &*)2n& &)* <escription: *)2n& &)*& (ma6e-string ;8 V ) &*)2n& &)*& (ma6e-string ;8 V=) &*)2n& &)* *)2n& &)*& (ma6e-string ;8 V=) &*)2n& &2n-include .iostream.h/2n&)))) (outline-minor-mode #) (or (file-exists-p &ma6efile&) (file-exists-p &Ja6efile&) (set (ma6e-local-4aria%le "compile-command) (concat &gPP -o & (su%string (file-name-nondirectory %uffer-file-name) @ (string-match &22.DT& (file-name-nondirectory %uffer-filename))) & & (file-name-nondirectory %uffer-filename))))))

;;; Jar6 hac6s ( setO perl-mode-hoo6 "(lam%da() (setO perl-indent-le4el @) (setO perl-continued-statement-offset 5) (setO perl-continued-%race-offset -5) (setO perl-%race-offset 5) (setO perl-%race-imaginary-offset @) (setO perl-la%el-offset -5) (define-6ey perl-mode-map &2D-m& "newline-and-indent) ) )

( setO Ua4a-mode-hoo6 "(lam%da() (setO Ua4a-indent-le4el @) (setO Ua4a-continued-statement-offset 5) (setO Ua4a-continued-%race-offset -7) (setO Ua4a-%race-offset 5) (setO Ua4a-%race-imaginary-offset @) (setO Ua4a-la%el-offset -7) (setO Ua4a-statement-%loc6-intro . P) (setO Ua4a-6nr-argdecl-intro . 5) (setO Ua4a-su%statement-open . @) (setO Ua4a-la%el . @) (setO Ua4a-statement-case-open . @) (setO Ua4a-statement-cont . @) (define-6ey Ua4a-mode-map &2D-m& "newline-and-indent) ) )

3nswers to @uestions
Dhapter # #) 1 tool which translates high le4el language into machine language. $) 9y typing the name of an executa%le file. 5) 9y typing something li6e &cc filename& 7) NGI 8) Dompiler errors and runtime errors. Dhapter 5 #) printf (&?ow %ig deal&); $) printf (&$$&); 5) printf (&3he 5 wise men&); printf (&3he 'd wise men&(5); 7) Jost facilities are held in li%raries Dhapter 7 #) 3o pro4ide a %asic set of facilities to the user $) 3he filename used %y a computer to reference a de4ice 5) accounts.c

7) accounts.x (or perhaps accounts.BCB) 8) 9y typing the name in 7) Dhapter 8 #) -include .filename/ or -include &filename& $) stdio.h 5) No. Gnly macro names can %e used if the header file is not included. 7) Header file. Dhapter ; #) 1 group of statements enclosed %y curly %races 0A. $) Domments( preprocessor commands( functions( declarations( 4aria%les( statements. (3his is a matter of opinion( of course.) 5) Not necessarily. t starts where4er main() is.

7) t signifies the end of a %loc6( the return of control to somethng else. 8) 3he semi-colon (;) Dhapter = #) 3he compiler thin6s the rest of the program is all one Dhapter > #) function (a(%) int a(%; 0 return (a*%); A $) No. 5) 3he 4alue is discarded. 7) 3he result is gar%age. 8) 9y using &return&. Dhapter #@ #) 1 name for some 4aria%le( function or macro $) a(c(f 5) int i(U; commentI

7) dou%le is twice the length of float and can hold significantly larger 4alues. 8) int can ha4e 4alues P or -. Unsigned can only %e P and can hold slightly larger P 4alues than int. :) = :;;

;) int =) 1t the function defintion and in the calling function. >) printf (&'d&((int)$5.#$8:); #@) No. Dhapter ## #) ?ith 4aria%le parameters or with return() $) ?here a function is definned( after its name: e.g. function (...) .-- here 0 A 5) \es. 7) No and it is illegal. 8) * means &the contents of& and M means &the address of& :) No. Dhapter #$ #) 1 glo%al 4aria%le can %e accessed %y any part of a program. $) 1 local 4aria%le canonly %e accessed %y a select part of a program. 5) Eocal 4aria%les cannot lea6 out. Nothing outside them can reach local 4aria%les. 7) Saria%le parameters do. Salue parameters use their own local copies( so they do not. 8) int i(U; main () 0 float x(y; another(x(y); A another(x(y)

float x(y; 0 A 3here are : storage spaces altogether. Dhapter #5 #) -define %irthday #> $) -include .math.h/ 5) false 7) false Dhapter #7 #) 1 4aria%le which holds the address of another 4aria%le $) ?ith a * character. e.g. int *i; 5) 1ny type at allI 7) dou%leptr = (dou%le *)chptr; 8) 9ecause num%er has not %een initialiNed. 3his expression initialiNes the place that num%er points to( not num%er itself. (+ee main text) Dhapter #8 printf #) -include .stdio.h/ main () 0 printf (&'$e&(:.$5); A $) 3his depends on indi4idual compilers 5) a) %) c) d) scanf #) space( newline or ta% 8) true. Eow le4el )G No con4ersion string Don4ersion string without matching 4alue ,ro%a%ly nothing Don4ersion string without matching 4alue

#) 3he statement is possi%le pro4ided putchar() is not implemented as a

macro. t copies the input to the output: a simple way of writing on the screen. (Note howe4er that the output is %uffered so characters may not %e seen on the output for some timeI) $) ch = getchar(); putchar (ch); Dhapter #: #) 3he thing(s) an operator acts upon. $) printf (&'d&(8 ' $); 5) rem = 8 ' $; 7) 4aria%le = #@ - -8; 8) if (# I= $5) 0 printf (&3han6 goodness for mathematics&); A Dhapter #= #) 3hree: while( do..while( for $) while : at the start of each loop do : at the end of each loop for : at the start of each loop 5) do..while 7) -include .stdio.h/ -define 3RUB # main () 0 char ch; while (true) 0 ch = getchar(); putchar (ch); A Dhapter #> #) 3he array identifier (without sOuare %rac6ets) is a pointer to the first element in the array. $) \ou pass the array identifier( without sOuare %rac6ets. NoI 1rrays are always 4aria%le parameters. 5) dou%le arrayX7YX8Y; Salid array %ounds from arrayX@YX@Y to arrayX5YX7Y Dhapter $@

#) 1rrays of characters. ,ointers to arrays of characters. $) static char *stringsXY; Dould then initialiNe with %races 0A and item list. (+ee main text) 5) +ee the Jorse code example. Dhapter $$ #) dou%le $) ,ro%a%ly true. 3his is implementation dependent. 3he actual types are dou%le( long float and int. 5) 3he length of a string (excluding NUEE %yte) 7) ^oins two strings. 8) G4erflow( underflow( domain error( Eoss of accuracy and di4ision %y Nero. Dhapter $5 #) PP( -- and any assignment or unary operator $) t could ma6e a program too difficult to read

5) No. 3he function would return %efore the 4aue could %e incremented. Dhapter $5 #) L EB is defined %y stdio.h t is reser4ed only when this file is included. t is not a %uilt in part of the language. $) L EB *fp; 5) Lalse. 3hey are meant for compariti4e purposes only. sense to do arithmetic with enumerated data. t does not ma6e

7) \es. t pro4ides a generic pointer. i.e. one which can %e assigned to any other pointer type. 8) 4olatile :) typedef dou%le real; ;) 3rue. Dhapter $7 #) Nothing -- only the way it is used. \es( e4ery 4aria%le is a %it pattern. t is normal to use integer or character types for %it patterns. $) nclusi4e GR is true if all possi%lilities are true simultaneously. Bxclusi4e GR is false if all possi%ilites are true simultaneously. 5) +ome 6ind of flag message perhaps. 1 %it pattern for certain.

7) a) %) c) d) e)

@@@@@### @@@@@@@# @@@@#### @@@@#### @@@@####

M M M M M

@@@@@@#@ @@@@@@@# @@@@@@## @@@@@### @@@@@###

== @@@@@@#@ == $ == @@@@@@@# == # == @@@@@@## == 5 == @@@@@### == ; M @@@@@@## == @@@@@@## = 5

8) a) @@@@@@@# Q @@@@@@#@ == @@@@@@## == 5 %) @@@@@@@# Q @@@@@@#@ Q @@@@@@## == @@@@@@## == 5 :) a) # M ([#) == @@@@@@@# M #######@ == @ %) $5 M [$5 == @@@##### M ###@@@@@ == @ c) similarly @: n M (NG3 n) is always Nero Dhapter $: #) a) a string which la%els a file %) a 4aria%le of type *fp which points to a L EB structure c) the num%er of a file &portal& in the )G array $) High le4el filing performs translations to text. Eow le4el files untranslated %it data. 5) fp = fopen (&filename&(&r&); 7) fd = open (&filename&(GK?RGNE\); :) fprintf () Dhapter $; #) 1 structure can hold se4eral 4alues at the same time. 1 union holds only one 4alue at any one time. $) 1 part of a structure( or a possi%le occupant of a union. 5) x.mem 7) ptr-/mem 8) Lalse. Dhapter $= #) 1 diagram which shows how structures are put together. $) ?ith pointers. 5) Lalse. ,ointers are used to reference 4aria%les and data structures are %uilt in such a way as to reOuire only one name for a whole structure. 7) ?ith pointers. ptr-/mem%er etc... 8) ptr=(struct 9inary 3ree *)malloc(siNeof(struct 9inary 3ree)); Dhapter $> #) 1 function which is defined in terms of itself.

$) 1 data structure run %y the D-language for 6eeping trac6 of function calls and for storing local data. 5) 1 lot of memory is used as stac6 space. Dhapter 5# #) <eclarations are in the wrong place. $) Jissing closing %race A 5) Jissing semi-colon after closing %race A;

Inde*

operator- Pointers a.out- The compiler 5ddress of varia,les- Pointers 5rra# pointer- 2unction pointers 5rra#s- 5rra#s 54C.. codes- Character Conversion Ta,le 5ssignment, hidden- Example "' +inar# tree- Example 4tructures +it operations- )achine Level 1perations +lac* ,oxes- 2unctions +races- 2orm of a C program C li,rar#- 1perating s#stems Calling functions- 2unctions case statement- switch Case, upper and lower- Use of Upper and Lower Case cast operator- T#pes and The Cast 1perator Casting pointers- Example ' char- 3aria,les Character classification- Character .dentification Character constants- char Character conversion ta,le- Character Conversion Ta,le Comments- Comments Compiler- +asic ideas Compiler phases- The compiler Compiling a program- 2ilenames Conditional compilation- 1ther Preprocessor commands const, constants- const Constant expressions- 4pecial Constant Expressions Constants and macros- Preprocessor Control characters- char Control characters, printf- 2ormatting with printf Conversion characters, scanf- Conversion characters
M

Conversion ta,le- Character Conversion Ta,le Curl# ,races- 2orm of a C program 6ata structures- 6ata structures 6e,ugging- Errors and de,ugging 6ecisions- 6ecisions 6eclarations- Use of Upper and Lower Case 6evices- 2iles devices do while- do while End of file- feof enum t#pe- 2.LE Enumerated data- 2.LE Environment varia,les- envp Environment varia,les in C- envp Eratosthenes sieve- 5rra#s and for loops Errors, diagnosing- Errors and de,ugging Errors, files- 2ile Errors Errors, of purpose- Errors Errors, programming- Errors Escaping from an program- Command languages Example code- Example Programs chapter exit function- The exit function Expressions- 2unctions with values Extern class- 4torage class register static and extern 2.LE- 2.LE 2ile descriptors- 2ile 7andles 2ile extensions- 2ilenames 2ile handles- 2ile 7andles 2ile, detecting end of- feof 2ile, opening- 1pening files 2iles- 2iles and 6evices 2iles and devices- 2iles devices 2iles as a,stractions- 4tandard 1utput and 4tandard .nput 2ormat specifiers, printf- 2ormatting with printf 2ormatting text and varia,les- printf 2unction names- 2unctions 2unctions- 2unctions 2unctions with values- 2unctions with values Game of life- Example "! gcc- The compiler getchar- getchar and putchar geten4() function- envp gets- gets and puts, getsBC Glo,al varia,les- Glo,al varia,les Glo,al varia,les and recursion- 5dvantages and 6isadvantages of /ecursion GNU compiler- The compiler 7eader files- Li,raries 7idden assignment- Example "'

7igh level- Levels .dentifier names- 2unctions if- 6ecisions if statement- if .nitialiAation of arra#s- .nitialiAing 5rra#s .nitialiAing structures- Pre;initialiAing 4tatic 4tructures .nitialiAing varia,les- 6eclarations and .nitialiAation int- integers, 3aria,les .nteger t#pes- 3aria,les .ntegers- integers .nterrupting a program- Command languages Ke#,oard input- 4tandard 1utput and 4tandard .nput La#out- Programming st#le Levels of detail- Levels Li,raries- /eserved words 0 example Li,raries of functions- Li,raries Lin*ed list- Example 4tructures Lin*er- The compiler Local environment- Levels Local varia,les- <here to declare things, Local varia,les Logical errors- Errors long- 3aria,les, integers Loop varia,les- Choosing 3aria,les Loops- Loops Low level- Levels )achine level operations- )achine Level 1perations )acros- Preprocessor main function- 2orm of a C program )ainframe- 1perating s#stems malloc- Creating )emor# for 6#namical struct T#pes )ath errors- )aths Errors )athematical functions- )athematical 2unctions )emor# allocation, d#namical- Creating )emor# for 6#namical struct T#pes )ultidimensional arra#s- 5rra#s 1f )ore Than 1ne 6imension Names, for identifiers- 2unctions Nested ifs- Nested ifs and logic Non;printa,le characters- char 1pening a file- 1pening files 1perating s#stem- 1perating s#stems 1perators- 5ssignments Expressions and 1perators 1perators, hidden- 7idden 1perators 1utput, formatting- printf Panic ,utton- Command languages Parameters to functions- Parameters Parsing strings- sscanfBC Phases of compilation- The compiler Poem- Example %

Pointers- Pointers Pointers to functions- 2unction pointers Preprocessor- Preprocessor Prime num,er generator- 5rra#s and for loops printf function- printf, printf again Printing- printf Printing formatted to strings- sprintfBC Protot#ping- 3alue parameters putchar- getchar and putchar puts- gets and puts, putsBC /ecords- 4tructures and Unions /ecords BstructuresC- struct again /ecursion- /ecursion /ecursion and glo,al varia,les- 5dvantages and 6isadvantages of /ecursion /eserved words- /eserved words 0 example /eturning values- 2unctions with values scanf- scanf scanf, dangers- The dangerous function 4cope- <here to declare things, 4cope 4creen editor- +asic ideas 4creen output- 4tandard 1utput and 4tandard .nput 4hell- +asic ideas, 1perating s#stems short- integers, 3aria,les 4na*es and ladders- Program listing 4pecial characters- 4pecial Control Characters again, char 4tac*- 2unctions and The 4tac* 4tandard error- 2iles devices 4tandard input- 2iles devices 4tandard inputEoutput- 4tandard 1utput and 4tandard .nput 4tandard output- 2iles devices 4tatic initialiAation of arra#s- .nitialiAing 5rra#s 4tatic varia,les- 4torage class register static and extern stderr- 4tandard 1utput and 4tandard .nput stdin- 4tandard 1utput and 4tandard .nput stdio.h- Li,raries stdout- 4tandard 1utput and 4tandard .nput strcmp- 7andling strings strcp#- 7andling strings 4treams- 4tandard 1utput and 4tandard .nput, 7ow does scanf see the input 4tring handling functions- 7andling strings 4trings- Conventions and 6eclarations strlen- 7andling strings strstr- 7andling strings 4tructure- struct again 4tructure of a C program- 2orm of a C program 4tructured data- 4tructures and Unions 4tructures- 4tructures and Unions

4tructures, initialiAing- Pre;initialiAing 4tatic 4tructures 4t#le- Programming st#le, if, Cautions a,out 4t#le 4t#le, glo,al varia,les- 4t#le note 4u,strings, searching for- 7andling strings switch case- switch 4#ntax error- Errors Ta,les- 5rra#s Terminating a program- The exit function Tests- 6ecisions T#pe conversion- T#pes and The Cast 1perator T#pes- T#pes and The Cast 1perator T#pes, advanced- )ore on 6ata T#pes Union- Unions Unions- union, 4tructures and Unions 3alue parameters- 3alue parameters 3aria,le names- 3aria,les 3aria,le t#pes- T#pes and The Cast 1perator 3aria,les- 3aria,les, Use of Upper and Lower Case 3aria,les, declaring- 6eclarations 3aria,les, initialiAing- 6eclarations and .nitialiAation void- void volatile- volatile <hiet space- Comments while loop- while <hite space- 4cope

"a le of !ontents

C Programming Tutorial BK0/ version C Preface .ntroduction o 7igh Levels and Low Levels o +asic ideas a,out C o The Compiler o Errors o Use of Upper and Lower Case o 6eclarations o >uestions /eserved words and an example o The printf() function o Example Listing o 1utput o >uestions 1perating s#stems and environments o 2iles and 6evices o 2ilenames

Command Languages and Consoles >uestions Li,raries o >uestions Programming st#le The form of a C program o >uestions Comments o Example % o Example " o >uestion 2unctions o 4tructure diagram o Program Listing o 2unctions with values o +rea*ing out earl# o The exit() function o 2unctions and T#pes o >uestions 3aria,les, T#pes and 6eclarations o 6eclarations o <here to declare things o 6eclarations and .nitialiAation o .ndividual T#pes
o o

Listing .ntegers o <hole num,ers 2loating Point o Choosing 3aria,les o 5ssigning varia,les to one another o T#pes and The Cast 1perator o 4torage class static and extern o 2unctions, T#pes and 6eclarations o >uestions Parameters and 2unctions o 6eclaring Parameters o 3alue Parameters o 2unctions as actual parameters o Example Listing o Example Listing o 3aria,le Parameters o Example Listing o >uestions 4cope - Local 5nd Glo,al o Glo,al 3aria,les o Local 3aria,les

char

Communication - parameters Example Listing 4t#le Note 4cope and 4t#le >uestions Preprocessor Commands o )acro 2unctions o <hen and when not to use macros with parameters o Example Listing o Note a,out -include o 1ther Preprocessor commands o Example o >uestions Pointers o M and * o Uses for Pointers o Pointers and .nitialiAation o Example Listing o T#pes, Casts and Pointers o Pointers to functions o Calling a function ,# pointer o >uestions 4tandard 1utput and 4tandard .nput
o o o o o o o o o o o o o o o o o o o o o o o o o printf

Example Listing 1utput 2ormatting with printf Example Listing 1utput 4pecial Control Characters >uestions
scanf

Conversion characters 7ow does scanf see the inputF 2irst account of scanf The dangerous function Keeping scanf under control Examples )atching without assigning 2ormal 6efinition of scanf 4ummar# of points a,out scanf >uestions Low Level .nputE1utput getchar and putchar gets and puts o >uestions 5ssignments, Expressions and 1perators

Expressions and values Example 1utput Parentheses and Priorit# Unar# 1perator Precedence 4pecial 5ssignment 1perators PP and -)ore 4pecial 5ssignments Example Listing 1utput The Cast 1perator Expressions and T#pes Comparisons and Logic 4ummar# of 1perators and Precedence >uestions 6ecisions
o o o o o o o o o o o o o o o o o o o o o o o if

Example Listings if ... else Nested ifs and logic Example Listing 4tringing together if..else switch- integers and characters Example Listing Things to tr#
while

Loops
o o o o o o o o o o o

Example Listing Example Listing do..while Example Listing


for

Example Listing The flexi,le for loop >uitting Loops and 7urr#ing Them Up: Nested Loops >uestions <h# use arra#sF Limits and The 6imension of an arra# 5rra#s and for loops Example Listing 5rra#s 1f )ore Than 1ne 6imension 5rra#s and Nested Loops Example Listing 1utput of Game of Life .nitialiAing 5rra#s 5rra#s and Pointers

5rra#s
o o o o o o o o o o

o o

5rra#s as Parameters >uestions Conventions and 6eclarations 4trings, 5rra#s and Pointers 5rra#s of 4trings Example Listing 4trings from the user 7andling strings Example Listing 4tring .nputE1utput
gets() puts() sprintf() sscanf()

4trings
o o o o o o o o

Example Listing >uestions Putting together a program o The argument vector o Processing options o Environment varia,les 4pecial Li,rar# 2unctions and )acros o Character .dentification o Examples o Program 1utput o 4tring )anipulation o Examples o )athematical 2unctions o Examples o )aths Errors o Example o >uestions 7idden operators and values o Extended and 7idden = o Example o 7idden PP and -o 5rra#s, 4trings and 7idden 1perators o Example o Cautions a,out 4t#le o Example o >uestions )ore on data t#pes o 4pecial Constant Expressions
o o o o o o L EB enum

Example Example

>uestions )achine Level 1perations o +it Patterns o 2lags, /egisters and )essages o +it 1perators and 5ssignments o The )eaning of +it 1perators o 4hift 1perations o Truth Ta,les and )as*ing Complement [ 5N6 M 1/ Q W1/EE1/ Z o Example o 1utput o Example o Example o >uestions 2iles and 6evices o 2iles Generall# o 2ile Positions o 7igh Level 2ile 7andling 2unctions o 1pening files o Closing a file
o o o o o o o o o o o o o o o o o fprintf() fscanf()

o o o o o o o o

4uggested uses for enum


4oid 4olatile const struct union typedef

s*ipfilegar,BC F 4ingle Character .E1 getc() and fgetc()


ungetc() putc() and fputc() fgets() and fputs()

feofBC Printer 1utput Example 1utput Converting the example 2iling Errors 1ther 2acilities for 7igh Level 2iles fread() and fwrite() 2ile Positions- ftellBC and fsee*BC

and remo4e() Example >uestions 4tructures and Unions o 1rganiAation- +lac* +ox 6ata o struct o 6eclarations o 4cope o Using 4tructures o 5rra#s of 4tructures o Example o 4tructures of 4tructures o Pointers to 4tructures o Example o Pre;initialiAing 4tatic 4tructures o Creating )emor# for 6#namical struct T#pes o Unions 6eclaration Using unions o >uestions 6ata 4tructures o 6ata 4tructure 6iagrams o The Tools- 4tructures, Pointers and 6#namic )emor# o Programme 2or +uilding 6ata 4tructures o 4etting Up 5 6ata 4tructure o Example 4tructures o >uestions /ecursion o 2unctions and The 4tac* o Levels and <ells o Tame /ecursion and 4elf;4imilarit# o 4imple Example without a 6ata 4tructure o 4imple Example <ith a 6ata 4tructure o 5dvantages and 6isadvantages of /ecursion o /ecursion and Glo,al 3aria,les o >uestions Example Programs

o o o o o o o o o o o o o

rewind() fflush()

Low Level 2iling 1perations 2ile descriptors


open() close() creat()

readBC
write() lsee6() unlin6()

4tatistical 6ata 7andler The Editor .nsertE1verwrite >uitting 4ections The Program Listing o Listing o 3aria,le Cross /eferencer Listing Cref.c 1utput of Cross /eferencer Comments Errors and de,ugging o Compiler Trappa,le Errors )issing semicolon@ )issing closing ,race A )ist#ping UpperELower Case )issing 8uote & 3aria,le not declared or scope wrong Using a function or assignment inside a macro 2orgetting to declare a function which is not t#pe int T#pe mismatch in expressions o Errors not trappa,le ,# a compiler Brun time errorsC Confusion of = and == )issing M in scanf Confusing CRR and RRC Unwarranted assumptions a,out storage The num,er of actual and formal parameters does not match The conversion string in scanfEprintf is wrong 5ccidental confusion of int, short and char 5rra#s out of ,ounds )athematical Error Uncoordinated 1utput using ,uffered .E1 Glo,al 3aria,les and /ecursion o Tracing Errors Locating a pro,lem o Pathological Pro,lems o Porting Programs ,etween computers o >uestions 4ummar# of C o /eserved <ords o Preprocessor 6irectives o 7eader 2iles and Li,raries o Constants o Primitive 6ata T#pes o 4torage Classes o .dentifiers o 4tatements o Character Utilities o 4pecial Control Characters
o

o o o o o

.nputE1utput 2unctions printf conversion specifiers scanf conversion specifers )aths Li,rar#
goto

5ll the /eserved <ords Three Languages- <ords and 4#m,ols Compared Character Conversion Ta,le Emacs st#le file 5nswers to 8uestions .ndex

You might also like