Prolog
Aims
The aim of this course is to introduce programming in the Prolog language. The cut operator and assert/retract are included to allow real uses of the language to be understood and to make the language an option to use in a Part II project. The course includes case studies of familiar algorithms in the declarative idiom.
Lectures
· Syntax and Unification. Prolog's slim syntax is described. Unification is described with examples to show how pattern matching is achieved.
· Lists, terms and arithmetic. The Prolog syntax is used to create lists and terms, and to perform simple arithmetic.
· Graphs. Classic graph algorithms are presented in the declarative Prolog style.
· Trees. Classic tree algorithms are presented in the declarative Prolog style.
· Non-determinism. The backtracking mechanism for finding alternative solutions is described and illustrated, with techniques to modify the default behaviour.
· Negation as failure. The reasons why Prolog saying ``No'' differs from ``false'' are discussed and illustrated.
· Difference structures. Difference lists are described and students participate in a re-write of programs from classical lists to difference lists.
· Using difference structures. Copying trees is used as an example to show the optimisations possible for large programs when the difference structure technique is used.
Objectives
At the end of the course students should
· be able to write programs in Prolog using techniques such as accumulators and difference structures.
· know how to model the backtracking behaviour of program execution.
· appreciate the unique perspective Prolog gives to problem solving and algorithm design.
· understand how larger programs can be created using the basic programming techniques used in this course.
Recommended reading
* Bratko, I. (2001). PROLOG programming for artificial intelligence. Addison-Wesley (3rd ed).
About Prolog
Prolog is short for PROgramming in LOGic, it is a logcial and declarative language. It is considered to be a very high level language, and was made particularly popular afte the Japanese government invested in its usage. You can get a good, free interpreter here.
Uses of Prolog
· Natural Language Systems
· AI
· Expert Systems
· Theorem Proving
Creating a Program
Programs are normally written in text
editors then interpreted by a prolog implementation. An example of a statment
is
likes(mary,food).
Note the full stop, they are important like the ; in other language.
Key commands
· You can see prologs actions as it works through a goal by tyiping trace.
· You can see what information prolog has recorded by typing listing.
Asking a question
You can tell prolog that bob is pats parent with parent (bob, pat).
You can can ask prolog who's pats parent with ?- parent (X, pat). and it should
return X=bob.
You can attatch two requirements together with a comma. For example parent (X,
Y), parent (Y, pat). will find the grandparent of pat.
There are three kinds of clauses in Prolog:
· Facts declare things that are always true
· Rules declare things are true dependant upon conditions
· Questions return what is true, and what makes a clause true. Unary relations are used to declare simple facts, eg; male(pat).
Goal finding
If a goal fails, prolog backtracks and will try another path.
Objects
Atoms start with a lower-case letter pat
is an atom in male(pat).
Variables start with an upper case letter. Structures have multiple components
eg; date(13,April,1976)
Lists can be made of any objects, even lists eg; [1, 2, 3, [pat, tom, mary ] ]
Backtracking
Automatic backtracking is useful as it
saves you having to program it explicitly, but it can be inefficient. The cut command is used to prevent
backtracking when it would be futile or if you don't want multiple answers.
If a variable is used only once an underscore character can be used in its
place.
Software
Engineering
Syllabus
Aims
This course aims to introduce the students to software engineering, and in particular to the problems of building large systems, safety-critical systems and real-time systems. Case histories of software failure are used to illustrate what can go wrong, and current software engineering practice is studied as a guide to how failures can be avoided.
Lectures
· The software crisis. Examples of large-scale project failure, such as the London Ambulance Service system. Intrinsic difficulties with software.
· The software life cycle. Getting the requirements right; requirements analysis methods; modular design; the role of prototyping; the waterfall, spiral and evolutionary models.
Friends: Read our GoTomeeting Reviews for information on how to hold online meetings.
· Critical software. Examples of catastrophic failure; particular problems with real-time systems; the difficulty of achieving ultra-high reliability; verification and validation.
· Quality assurance. The contribution of reviews and testing; reliability growth models; software maintenance and configuration management; life cycle costs.
· Tools. The effect of high-level languages; object-oriented systems and object reuse; an overview of formal methods with some application examples; project planning tools; automated testing tools.
· Large software systems. The role of application domain knowledge; changing requirements; risk reduction versus due diligence; communications failure; organisational factors.
Objectives
At the end of the course students should know how writing programs with tough assurance targets, in large teams, or both, differs from the programming exercises they have engaged in so far. They should appreciate the waterfall, spiral and evolutionary models of software development and be able to explain which kinds of software project might profitably use them. They should appreciate the value of other tools and the difference between incidental and intrinsic complexity. They should understand the software development life cycle and its basic economics. They should be prepared for the organisational aspects of their Part IB group project.
Recommended books
* Pressman, R.S. (1994). Software engineering. McGraw-Hill.
Leveson, N. (1994). Safeware.
Addison-Wesley.
Maguire, S. (1993). Writing solid code.
Microsoft Press.
Further reading:
Brooks, F.P. (1975). The mythical man month. Addison-Wesley.
Neumann, P. (1994). Computer-related
risks. ACM Press.
Report of the inquiry into the London
Ambulance Service (SW Thames RHA, 40 Eastbourne Terrace, London W2 3QR,
February 1993).
http://www.cs.ucl.ac.uk/staff/A.Finkelstein/las.html
Anderson, R. (2001). Security engineering (Chapters 22 and 23). Wiley. Also
available at
http://www.cl.cam.ac.uk/users/rja14/book.html
Introduction
Software Engineering is often overlooked
in computer science courses, however experienced programmers should know its value.
As software projects increase in size, they likelihood of failure increases up
to almost 50%.
Software engineering is hard becuase it is about managing complexity. Much of
the incidental complexity can be removed using tools (such as high level languages,time
sharing and integrated development environments) but the intrinsic complexity
remains.
The following pages are intended to give an overview of this vast subject, and
are mainly culled from lecture notes and classic papers.
Rates of Software Engineering Failure
| Requirements | Very High |
| Specification | Low |
| Design | Low |
| Implementation | Low |
| Installation | High |
| Operation | Enormous |
| Maintenance | Very High |
Requirements
The rate of failure is high for requirements as they are developed by two or more groups of people who come from different disciplines and speak different languages.
Specification,Design,Implementation
These activities are done by a group of similarly disciplined professionals.
Installation
Installation is often done by people who weren't involved in the implementation and don't understand the system.
Operation
Operation is often left to people who
dont understand the system or what it is meant to achieve.
Robert Courtney, a New York security consultant, examined thousands of security
beaches in both industry and government and found that 68% of them were due to
careless operations or incompetent operations.
Maintenance
Maintenance is often done as an afterthought by people who dont understand what they are changing.
Stages in the Software Life Cycle
Abstract
The Software Life Cycle Model consists of the System Development Cycle and the System Maintenance Cycle.
The software life cycle (according to
IEEE1074) starts with the selection of an appropriate life cycle model followed
by recruitment. There are many life cycle models that can be chosen. The
following stages are in the sequential order of the Waterfall Model, due to its
simplicity and prevalance in software engineering.
· Project planning and a feasibility study are required to determine first of all if a new system is needed, and if it is possible within reasonable costs and time restraints.
· Requirement analysis is one of the first stages in the waterfall model, in which the requirements of the new system are found through interviews with potential users and management, and feedback on prototypes. It is important that those chosen to be interviewed are technically capable or the interviewer can extrapolate what the user wants form their feedback and spot possible requirement contradictions.
· From the requirements a formal specification can be written up; normally a strict and mathematical description of what the system must achieve. These come directly from the requirements, and may follow more informal specifications. When the application is further into the development cycle it will be continuously checked against the specifications to ensure the system fulfils the its required purpose.
· The central stage in the waterfall model is the implementation and (unit & system) testing. Implementation is the most obvious part of creating a system, but often one of the smaller sections time and cost wise. Testing is important to prevent bugs and to test the implementations against the specifications. A failure is generally considered to be when a system doesn't perform as intended, whilst a fault is a programming error that may develop into a failure. It is important testing is thorough,as the earlier a defect is detected the cheaper it is to fix. Testing generally starts during the requirement analysis stage of the software development life cycle. Testing then continues into the development and then execution stages. Unit testing typically follows implementation, followed by integration testing.
· Acceptance, installation and deployment are the final stages of initial development where the software is put into practice and runs actual business. Choices in deployment time and back up strategies in case of system failure are essential for critical services (eg the failure of the LAS to have a back up ambulance system to switch back to after the failed system deployment).
· Training and support of the users then increases the likelihood of correct usage of the system.
· Maintenance can be a very expensive task, as it essentially lasts as long as
the system. It may require some of the original programmers to be employed
continuously to ensure the correct running of the system and for keeping it
appropriately up to date. If requirements change at a late stage it can prove
very expensive.
Typically about 40% of development time is spent in the requirements stage of
the life cycle, just 20% in the actual implementation and the remaining 40% in
testing.
Links & Resources
At the time of writing (Dec 06) the following resources were useful
· Software Develoment Process Wikipedia.org
· Quick Study Notes Computerworld.com
· The
Mythical Man Month Fred Brooks
Validation and Verification
Validation
In the waterfall model, validation operations provide feedback from Specification to Requirements and from Implementation/unit testing to Specification.
· Validation can be thought of as "Are we building the righy system?"
Verification
Verification operations provide feedback from Integration/ system testing to Implementation/unit testing, and from operations/maintenance back to Integration/system testing.
· Verification asks "Are we building this system right/correctly?"

The waterfall model
is reportedly employed by both the US D.O.D and NASA as their main software
development model, due to its strict design practices and clear progress
markers. This is despite being described as "risky and invites failure" by
W.W.Royce, who . originally created the term "Waterfall model" and criticized
it in favor of an iterative approach.
The waterfall model is a top down sequential model split into the sections
shown in the software
life cycle article, and illustrated by the image below
Image
by Paul A. Hoadley, Creative Commons license
Note that:
· Requirements are written in the user's language
· Specification is written in system language
· Unit testing checks units against the spec
·
System testing checks the
requirements are met
The waterfall model is well understood and time tested but generally considered
to be less useful than it once was due to the increasing complexity of systems.
It "works well for automating the tasks of clerks and accountants, less well
for knowledge works such as experts trying to solve problems" (Information Center
Quarterly article, Larry Runge). Another problem is that in the waterfall model
users only input is in specifying requirements and that all requirements must
be specified at one points before production begins. However, requirements
typically change through the process and require more feedback.
Summary of advantages:
· Easy for managers to understand, plan by and to test progress against as it has very clear sequential milestones
· Encourages good design practices such as early clarification of system goals, which in turn save time and money (the earlier a bug is caught, the less harm it can cause)
· Due to lots of up front design planning, should the project be stopped and taken up at a later date, or should project members change, implementation can continue far easier than with more agile development models where there is considerably less design documentation.
·
Compatible with a wide range of
design strategies
Summary of disadvantages
· Users may change requirements often, at stages beyond the requirements stage
· Users may not be able to state requirements until they see a working prototype that they can criticise
· At the implementation stage programmers may find that there is a near impossible problem to implement, and it may be easier to change the original design than to proceed ahead as planned.
· Constant verification of each stage is required to ensure that the next phase can start on a correct base
· Technology may change during development
Most of the problems of the waterfall model are solved by iterative and
evolutionary models such as the Spiral
Model
The Spiral Model
Iterative Design
One of the main objections to the
waterfall model is that in the real world requirements change during design for
a number of reasons: you simply cant create a specification at the start of a
project and expect it to be the same when the project is completed.
The solution to these objections is the notion of iterative development, where
there is feedback between prototypes and design.
The Spiral Model
The spiral model (Barry Boehm, 1988)
attempts to combine the advantages of the waterfall model with the flexibility
of an iterative approach.
Advantages
· Estimates (i.e. budget, schedule, etc.) get more realistic as work progresses, because important issues are discovered earlier.
· It is more able to cope with the (nearly inevitable) changes that software development generally entails.
· Software engineers (who can get restless with protracted design processes) can get their hands in and start working on a project earlier.
Further reading
· A Spiral Model of Software Development and Enhancement (PDF) - Barry Boehm's original article
Brooks Law
Abstract
The Mythical
Man Month attacked the idea that men and months are interchangeable in
software engineering. Brook wrote "Oversimplifying outrageously, we state
Brooks' Law:"
"Adding manpower to a late software
project makes it later."
Factors
·
Communications Complexity The more
people, the more communications complexity.
b people means n(n-1)/2 channels and 2n cliques)
· Training new people takes time
Example
Consider a project predicted to take 4 months with 3 men.
· However, the design falls behind and takes 2 months not 1! So there are two months (x3 men = 6 man months) left to do work that was originally estimated at 9 man-months
· 6 men are added to ensure that the project is done in time.
· But tTraining takes 1 month so all the 9 man-months must be done in the last month.
· However, the work that 3 men could do in 3 months can't be done by 9 men in 1 month (complexity, interdependencies, testing, ...) Hence Brooks law, also stated by himself as "The bearing of a child takes nine months, no matter how many women are assigned."
Further reading
· See Boehms Emprical Study for the results of empirical studies into Brooks law.
· Brooks' Law Repealed? IEEE Software, November/December 1999
Critical Software
Safety Critical Software
Systems where failure could cause death or injury are called safety critical systems. For example, nuclear reactor and flight control systems.
Security Cricital Software
Systems where failure could lead to reavealing classified, confidential business or personal data are called security cirtical systems. For example, payroll systems.
Business Critical Software
Systems where failure could affect
important operations are called business
critical systems.
Example- Patriot Missiles
Anti-missile patrior missiles failed to intercept an Iraqi SCUD missile on 25/2/91- the SCUD struck a US barracks in Dhahran. Other SCUD's got through to Isreal and Saudi Arabia.
Reason for failure
· The system measured time in 1/10 sec, truncated from binary representation .0001100110011....
· As the system was upgraded from anti-aircraft to anti-missile, greater accuracy introduced - but not everywhere in the code
· Two modules got out of step by 1/3 sec after 100 hours operation. Target not acquired
· Defect not found in testing as the spec called for 14 hour
continuous operation only
Many critical systems failures are multifactorial: "a reliable system
can't fail in a simple way"
Particular Problems of Large Systems
In 1988 Curtis,Kramer and Iscoe studied 17 large systems and why they failed. Over 97 interviews team and organistational factors were investigated. The main findings were that large software projects fail because of 1. A thin spread of applciation domain knowledge
· 2. Fluctuating and conflicting requirements
· 3. Breakdown of communication and coordination
They found the tytpical progression to disaster was 1 -> 2 ->3
Thin spread of application domain knowledge
It is rare to find someone who understands the entire solution. In some areas, eg pilot training, there is a structured effort to overcome this. Otherwise, with luck, you may get a genuine "guru" but even then you can expect specification mistakes.
Changing requirements
Competing products, new standards, new equipment and new users all combine to changing requirements.
Communication problems
Problems with communications increase with the more layers and more managers. Coping mechanisms such as committees increase the hierarchy. Managers are often loth to believe bad news, much less pass it on.
The Capability Maturity Model
By the mid-80's people had begun to
realise the importance of keeping teams together. The ability to work as a team
grows over time, this is the basis of the "capability maturity
model".
As well as a team, good management is required.
Hazards
Hazard Analysis
The Federal Aviation Administration (FAA) recognizes five categories of failure conditions and five software-level definitions.
Categories of Failure
| Failure Condition | Software Level |
| Catastrophic | Level A |
| Hazardous/Severe - Major | Level B |
| Major | Level C |
| Minor | Level D |
| No Effect | Level E |
In practice, the differences between levels A and B are small:
· Certain objectives of the software design process must be independently verified.
· Source code accuracy, consistency, and compliance with the software architecture must be independently verified.
· Robustness of object code with low-level requirements must be independently verified.
· Test coverage of software structure (modified condition/decision)
must be satisfied independently for level A, and is optional for level B and
lower.
Different hazard categories require different failure rates and ifferent levels
of investment in varying software engineering techniques. For example, a
nuclear capable US navy cruiser had ten seperate stages of analysis (eg
subsystem analysis, radiation hazard analysis, inadvertant launch analysis)
which overlapped and on which the development was based, rather than being
added retrofitted.
Hazard Elimination
Many hazards can be eliminated by small changes in design.
· Eg Motor reversing circuit:
If the switches dont move together there is a short circuit, and a fire could
occur.
The solution is to redesign so it is intrinsically safe. Intrinsically safe
software is the holy grail, however this normally requires a system level
approach.
Nuclear reactors normally have mechanical fail safes as you can never
completely trust software (unless it is a tiny program that you can prove
mathematically). Eg pebble
bed reactors which are self controlling (as the reactive pebbles and the
gas around them heat up, they push each other apart)
Documentation
A typical project has a number of management and engineering documents. As well as being useful for people outside the original development to read, documents can act as a contract.
Engineering Documents
· Requirements
· Hazard analysis
· Specification
· Test plan
· Code
Management Documents
· Contracts
· Budgets
· Activity charts and graphs
· Staff schedules
Methods of Ensuring Sufficient Documentation
· High tech: CASE tool
· Bureaucratic: Plans and controls dept
· Convention: Self documenting code
Testing
Testing can take up to half the cost of development in industry.
Bill Gates: "are we in the business of writing software, or test
harnesses?"
Testing takes place at a number of levels:
· Validation of the initial design
· Module test after coding
· System test after integration
· Beta test/field trial
· Subsequent litigation
· ...
Note that testing earlier is far less expensive than testing late.
Regression testing
The major advance in package software in
the last ten years has been in testing.
Regression testing involves checking that the new version of the software gives
the same answers as the old version.
A database is continually updated, containing every bug ever found. Unless all
previous bugs are tested for bugs have a ~20% chance of reoccuring
unexpectedly. It is best to test data given by real users, as this is what is
most likely to be noticed.
Reliability growth models help us asses mean time to failure, the number of
bugs remaining and the economics of further testing. It is found emprically.
Based on these models the rate of software failure drops exponentially at
first, then settles down to decrease at k/t.
Changing testers often makes new bugs visibile, as shown below
Failure to understand the environment in which the system will actually be
deployed often leads to incorrect testing and failures. A military approach (a
hostile review followed by prolonged field testing) can be very effective, but
in industry corporate politics normally prevents a wide uptake of good
practices.
Risk Reduction vs Due Diligence
Often one can never be certain about how many bugs are left. Organisations are highly averse to such uncertainty and prfer to avoid risk issues. Legal and cultural pressures replace risk reduction with "due diligence": a standard (but often insufficient) checklist is followed to ensure the legal pressures are satisfied but often not the problem itself.
Summary
A lack of consistent testing can cause
programs to behave incorrectly, fail or be insecure. For example in March 2002
it was reported that software bugs in Britain's national tax system resulted in
more than 100,000 erroneous tax overcharges. The problem was partly attributed
to the difficulty of testing the integration of multiple systems.
Testing is important as there will inevitably be bugs in any program of
significant length. These may be caused by a variety of factors at various
stages in the development cycle. The earlier a defect is found the cheaper it
is to fix -if a product has to be recalled due to a serious fault the cost can
be enormous. Inadequate testing may mean no one notices a problem until a vital
system crashes. Testing itself however can be very time consuming and expensive
and there can never be testing of 100% of real world situations in any program
of complexity. More safety critical and military projects will employ greater
testing, through large amounts of simulation testing. Often mathematical proofs
will be used to show that algorithms work in theory, complementing real world
tests.
There are numerous testing techniques and models, application depends upon who
the final system is for. Tests can be broadly split into black box tests
(external, based on functionality) and white box testing (based on knowledge of
the internal workings of the program, following branches etc.) Unit testing
tests particular methods and is useful for the micro scale examination of
individual parts of a program.
If the product is mass produced a company will generally factor the cost of
testing against the possible cost of a recall. For such mass market software
often beta testing is used, where large numbers of volunteers test the product
and report errors before the final product is shipped. This will test common
errors as the people testing are fairly normal users, but they lack the
expertise to test extreme cases and to notice many bugs and their causes.
In a "test-driven software development model" unit tests are written first, and
as more and more code of the main project is written less and less of the unit
tests are failed.
In a clean room process probabilities are assigned to paths users can take both
correct and incorrect, and the most common paths are tested more thoroughly.
This method was employed by Ericson in their OS development, cutting errors
down to 1 per 1000 lines of code, down from the industry average of about 25
per 1000 (Scientific American, 1994).
A good test engineer will have the ability to take the point of view of the
customer, a desire for quality and attention and good judgement on where to
focus testing efforts with scarce time resources.
Alternative Philosophies and Extreme Programming
Chief Programmer Teams
Chief programmer teams were developed at
IBM (70-72) to capitalise on the fact that some programmers are far more
productive than others- often by a factor of ten or more.
The team revolves around one chief programmer, one apprentice/assistant, a tool
smith, a librarian, an administrative assistant etc. to get the maximum
productivity from the available talent.
These teams can be very effective during the implementation stage of a project,
and is complementary to project management methodologies eg; Waterfall/ Spiral.
Ego less Programming
Ego less programming (Weinberg, 1971) is in direct opposition to the "chief programmer team" idea; code should be owned by the team not an individual.
Literate Programming
The code should be a work of art, designed not just for the machine but also for subsequent human readers. Code designed to be elegant may take far longer to develop than code designed more practically.
Definitions
Some of these definitions are particular to software engineering, especially the contradictory definitions of fault in computer science and electrical engineering (see below).
· An error is a design flaw, or deviation from the intended state
· A failure has occurred if the system hasn't performed in some subset of the specified environmental conditions
· In Computer Science, a fault is produced by an error which in turn produces a failure. Whereas in electrical engineering an error produces a failure which produces a fault.
· Reliability is measure as the "mean time to failure"
· An accident is an unintended event that results in a specific level of loss
· A hazard is a set of conditions on the system, if occur with certain environmental conditions (ie a failure), will lead to an accident.
· The risk is the probability of a hazard and its severity combined with the exposure (ie how likely the hazard is to cause an accident)
· Safety relates to freedom from accidents
C and C++
Lecturer: Dr A.R. Beresford
No. of lectures: 8
Prerequisite courses: None, though Operating Systems would be helpful.
Aims
The aims of this course are to provide a solid introduction to programming in C and C++ and to provide an overview of the principles and constraints that affect the way in which the C and C++ programming languages have been designed and are used.
Lectures
· Introduction to the C language. Background and goals of C. Types and variables. Expressions and statements. Functions. Multiple compilation units. [1 lecture]
· Further C concepts. Preprocessor. Pointers and pointer arithmetic. Data structures. Dynamic memory management. Examples. [2 lectures]
· Introduction to C++. Goals of C++. Differences between C and C++. References versus pointers. Overloading functions. [1 lecture]
· Objects in C++. Classes and structs. Operator overloading. Virtual functions. Multiple inheritance. Virtual base classes. Examples. [2 lectures]
· Further C++ concepts. Exceptions. Templates and meta-programming. STL generic programming. Examples. [2 lectures]
Objectives
At the end of the course students should
· be able to read and write C and C++ programs
· understand the interaction between C and C++ programs and the host operating system
· be familiar with the structure of C and C++ program execution in machine memory
· understand the object-oriented paradigm presented by C++
· be able to make effective use of templates and meta-programming techniques as used in the STL
· understand the potential dangers of writing programs in C and C++
Recommended reading
* Eckel, B. (2000). Thinking in C++,
Vol. 1: Introduction to Standard C++. Prentice Hall (2nd
ed.). Also available at
http://www.mindview.net/Books/TICPP/ThinkingInCPP2e.html
Kernighan, B.W. & Ritchie, D.M. (1988). The C programming language.
Prentice Hall (2nd ed.).
Stroustrup, B. (1994). The design and evolution of C++. Addison-Wesley.
Lippman, S.B. (1996). Inside the C++ object model. Addison-Wesley.
History
C is the successor to B, which was a
stripped down version of the BCPL language.
It became particularly popular when the Unix system was re-written in C in
1973.
Abstract
C is a very low level language, and is designed to be as minimal as
possible. For this reason it generally produces very efficient programs that
are simliar to those hand coded in assembler.
In particular, C has the following properties:
· Weak typing: For example you can create a character then treat it as an integer.
· A very simple core language, which relies heavily on importing libraries for extended functionality
· A preprocessor, which performs simple text manipulations
Hello World
As always, the best introduction to C is
through a very simple introduction:
/* The
pre-processor replaces this line with the contents of stdio.h */
#include
/* The special function main, which is loaded first,
returns an integer and takes no arguments */
int main(void)
/* Call the function printf, included in stdio.h, with
the string "Hello, world" */
{printf("Hello, world\n");
/* Return a 0, to indicate successful execution */
return 0;
} Compiled
with:
$ cc example1.c
Execute program with:
$ ./a.out
Hello, world
Basic Types
C has a small set of built-in types:
| type | description | format | example |
| char | characters (>8 bits) | character | 'c' |
| int | integer values (> 16 bits, normally one word) | number, escape sequence etc. | 12 |
| long int | long integers | suffix L | 2165L |
| float | ~real | Number with '.','e',or 'E' and suffix f | 1.23e45f |
| double | ¬real | number with '.','e' or 'E' | 1.324e5 |
Data type sizes
Data type sizes are platform specific, the following is a typical example:
Type Bytes Bits Range
short int 2 16 -32,768 -> +32,767 (32kb)
unsigned short int 2 16 0 -> +65,535 (64Kb)
unsigned int 4 32 0 -> +4,294,967,295 ( 4Gb)
int 4 32 -2,147,483,648 -> +2,147,483,647 ( 2Gb)
long int 4 32 -2,147,483,648 -> +2,147,483,647 ( 2Gb)
signed char 1 8 -128 -> +127
unsigned char 1 8 0 -> +255
float 4 32
double 8 64
long double 12 96
Source: phim.unibe.ch
Variables
Variables must be defined exactly once,
eg;
int i = 4;
· Global or static variables are declared outside variables and are accesible anywhere. Static is used with global variables and functions to set their scope to the containing file.
· A const variable can only be assigned a value when it is defined. Egg;
const int *const p is a const
pointer to a const int
· The volatile keyword can be used the warn the compiler that a variable may be
affected by hardware etc.
typedef can be used to create synonyms for types, eg;
typedef Wheels int;
Wheels w = 5;
Operators
| type | operators |
| arithmetic | + - * / ++ -- % |
| logic | == != > >= < <= || && ! |
| bitwise | | & << >> ^ ~ |
| assignment | = += -= *= /= %= <<= >>= &= |= ^= |
Enum
Enumeration is used to set constants. It
will automatically assign the predecessor +1 unless otherwise specified.
For example:
enum boolean
{F,T,FALSE=0,TRUE,N=0,Y}
Will assign F=0,T=1,FALSE=0,TRUE=1,N=0,Y=1.
Type Conversion
Unlike Java, C allows you to treat
variables pretty much as what you want. You can also assign larger types (eg
float) to smaller types (eg chars), causing an overflow but no compiler error
eg;
int i = 1234;
char c;
c = i+1; /* i overflows c */
Arrays
One or more objects of the same type can
be grouped into an array. Eg;
long int j[5];
Strings are just arrays of characters, terminated with the special \0
character.
char hi[] ="hello
world";
C doesnt require you to set the size of string arrays, saving you having to
work it out yourself.
When passing multi dimensional arrays to a function the the first dimension
doesnt have to be specified as you will get setting it later. Eg;
void example(int i[][3]) { }
Functions
A function that is defined without
values, eg example(), means that the arguments shouldnt be type-checked.
Void functions dont return values.
A function can be declared inline, telling the compiler insert the complete body of the function in
every context where that function is used.
The Pre-Processor
The pre processor can be used for textual
substitutions. Note that it is only used as a "search and replace"
tool before the compiler.
We have already met #include, used to copy a file into the source.
There are also conditional directives, #if #else #elif #endif
Particularly powerful is define:
#define PI 3.141592654 /*Replaces PI with 3.141592654
#define square(a) (a)*(a) /*Replaces a with a*a */
Pointers

In the example above, ppi is a pointer to a pointer, pi, which is a pointer to
the integer value 7.
Pointers just contain the memory address of what they point to. The more
memory, the larger pointers will have to be.
| operator | description | example |
| * | Retrieve/set the value pointed to |
int x = *pi; x now contains the value that pi points to, 7. |
|
int *pi = 5; The value that pi points to, i, is now set to 5. |
||
| & | Returns the memory address |
int x = π x now contains the memory address pi points to, 0x9d. |
The void pointer, void *p, can be used to point to any type. Whilst useful in
dealing with dynamic memory, it is bad practice to use it unless necessary.
Pointers can be used to index into arrays. Eg; char str[] "hello";
char *pc = str; /* pc now points to the beginning of the array */
*pc = &str[1]; /* pc now points to the second element : h */
Pointer Arithmetic
If pc points to the first element, after pc +=2;, pc
then points to the third element.
pc[2] represents the value of the element two head of the element pointed to by
pc.
Structures
Creating a structure creates a new type
that contains one or more variables. For example:
struct square {int x; int y}; /*
Define a structure square */
struct square c = {3,4}; /* Create an instance of square *
Members can be accessed with structname.member;
You can also create a pointer to a strucutre with struct square *pc
A structure can contain a member that is a pointer of the same type, eg; trees and linked lists.
Unions
A union is a single variable which can hold one of a number of different types, its size is that of the largest member.
Bit Fields
Bit fields are low level access to individual bits of a word. Specified inside a struct.
Volatile, Const, Typedef and Inline
The volatile keyword can be used to state that a variable can be changed by hardware.
A const variable can only be assigned a value when it is defined.
Typedef creates a synonym for a type.
Inline tells the compiler to call the function faster.
Dynamic Memory Allocation
Dynamic memory allocation is supplied by stdlib.h with malloc.
