P. 1
36853207 C Programming Ppt

# 36853207 C Programming Ppt

|Views: 524|Likes:

See more
See less

07/27/2013

pdf

text

original

## Sections

• Course Objectives
• Practical Exercises
• Features of C
• History of C
• Standard C vs K&R C
• A C Program
• The Format of C
• Another Example
• Variables
• Integer Types in C
• Integer Example
• Character Example
• Integers With Different Bases
• Real Types In C
• Real Example
• Constants
• Warning!
• Named Constants
• Preprocessor Constants
• Take Care With printf And scanf!
• Summary
• Operators in C
• Arithmetic Operators
• Using Arithmetic Operators
• The Cast Operator
• Increment and Decrement
• Prefix and Postfix
• Truth in C
• Comparison Operators
• Logical Operators
• Logical Operator Guarantees
• Bitwise Operators
• Bitwise Example
• Assignment
• Other Assignment Operators
• sizeof Operator
• Conditional Expression Operator
• Precedence of Operators
• Associativity of Operators
• Precedence/Associativity Table
• Review
• Control Flow
• Decisions - if then
• if then else
• Nesting ifs
• A switch Example
• (Another) Semicolon Warning!
• while, Not Until!
• for Loop
• for Is Not Until Either!
• Stepping With for
• Extending the for Loop
• Functions
• The Rules
• Writing a Function - Example
• Calling a Function - Example
• Calling a Function - Disaster!
• Prototypes
• Prototyping is Not Optional
• Writing Prototypes
• Take Care With Semicolons
• Example Prototypes
• Example Calls
• Rules of Visibility
• Call by Value
• Call by Value - Example
• C and the Stack
• Stack Example
• Storage
• Global Variables
• Pointers
• Pointers - Why?
• Declaring Pointers
• Example Pointer Declarations
• The “&” Operator
• Rules
• The “*” Operator
• Writing Down Pointers
• Initialisation Warning!
• Initialise Pointers!
• NULL
• A World of Difference!
• Fill in the Gaps
• Type Mismatch
• Call by Value - Reminder
• Call by Reference
• Pointers to Pointers
• Arrays in C
• Declaring Arrays
• Examples
• Accessing Elements
• Array Names
• Passing Arrays to Functions
• Example
• Using Pointers
• Pointers Go Backwards Too
• Pointers May be Subtracted
• Using Pointers - Example
• * and ++
• Which Notation?
• Strings
• Printing Strings
• Null Really Does Mark the End!
• Assigning to Strings
• Pointing to Strings
• Multidimensional Arrays
• Structures in C
• Concepts
• Setting up the Template
• Creating Instances
• Initialising Instances
• Structures Within Structures
• Accessing Members
• Unusual Properties
• Instances may be Assigned
• Passing Instances to Functions
• Pointers to Structures
• Pass by Reference - Warning
• Returning Structure Instances
• Printing the List
• Introduction
• SOAC
• Example 1
• Example 2
• Example 3
• Example 4
• Example 5
• Example 6
• Example 7
• Example 8
• Example 1 Revisited
• Example 3 Revisited
• Example 5 Revisited
• Example 6 Revisited
• Example 7 Revisited
• Example 8 Revisited
• Handling Files in C
• Streams
• What is a Stream?
• stdin is Line Buffered
• Opening Files
• Dealing with Errors
• File Access Problem
• Displaying a File
• Example - Copying Files
• Convenience Problem
• Accessing the Command Line
• Useful Routines
• Binary Files
• Miscellaneous Things
• Unions
• Remembering
• Enumerated Types
• Using Different Constants
• The Preprocessor
• Including Files
• Pathnames
• Avoid Temptation!
• Preprocessor Macros
• A Debugging Aid
• Working With Large Projects
• Data Sharing Example
• Data Hiding Example
• Disaster!
• Getting it Right
• Be as Lazy as Possible
• C and the Heap
• What is the Heap?
• How Much Memory?
• Dynamic Arrays
• Using Dynamic Arrays
• realloc Example
• realloc can do it all
• Allocating Arrays of Arrays
• Dynamic Data Structures

# Course Objectives

     Be able to read and write C programs Understand all C language constructs Be able to use pointers Have a good overview of the Standard Library Be aware of some of C’s traps and pitfalls

Practical Exercises
 Practical exercises are a very important part of the course  An opportunity to experience some of the traps first hand!  Solutions are provided, discuss these amongst yourselves and/or with the tutor  If you get stuck, ask  If you can’t understand one of the solutions, ask  If you have an alternative solution, say

Features of C
      C can be thought of as a “high level assembler” Designed for maximum processor speed Safety a definite second! THE system programming language (Reasonably) portable Has a “write only” reputation

History of C
 Developed by Brian Kernighan and Dennis Ritchie of AT&T Bell Labs in 1972  In 1983 the American National Standards Institute began the standardisation process  In 1989 the International Standards Organisation continued the standardisation process  In 1990 a standard was finalised, known simply as “Standard C”  Everything before this is known as “K&R C”

Standard C vs K&R C      Parameter type checking added Proper floating point support added Standard Library covered too Many “grey areas” addressed New features added  Standard C is now the choice  All modern C compilers are Standard C  The course discusses Standard C .

A C Program tells compiler about standard input and output functions (i.h> /* comment */ /* comment */ main function “begin” int main(void) int main(void) { { printf("Hello\n").e.h> #include <stdio. } } “end” return 0. return 0. printf("Hello\n"). printf + others) #include <stdio. Hello Hello Welcome to the Course! Welcome to the Course! flag success to operating system . printf("Welcome to the Course!\n"). printf("Welcome to the Course!\n").

those forgetting to do so have one or other chosen randomly! .all keywords and Standard Library functions are lowercase  Strings are placed in double quotes  Newlines are handled via \n  Programs are capable of flagging success or error.The Format of C  Statements are terminated with semicolons  Indentation is ignored by the compiler  C is case sensitive .

b.%i = %i\n". scanf("%i %i". printf("%i . b. int a.Another Example create two integer variables. &b). printf("Enter two numbers: ").17 = 4 21 . return 0. b.h> #include <stdio. printf("Enter two numbers: "). a . &a. “b” and “a-b” in the format specified } } return 0.b). scanf("%i %i". a. write “a”. a.%i = %i\n". b.17 = 4 read two integer numbers into “a” and “b” .b). “a” and “b” #include <stdio. a .h> int main(void) int main(void) { { int a. Enter two numbers: 21 17 Enter two numbers: 21 17 21 . &b). &a. printf("%i .

but are ignored)  Some implementations recognise only 6 characters in global variables (and function names)!  Upper and lower case letters are distinct . digits and “_”  First character cannot be a digit  31 characters recognised for local variables (more can be used.Variables  Variables must be declared before use immediately after “{”  Valid characters are letters.

this will be investigated later) .printf and scanf  printf writes integer values to screen when %i is used  scanf reads integer values from the keyboard when %i is used  “&” VERY important with scanf (required to change the parameter.absence will make program very ill  “&” not necessary with printf because current value of parameter is used .

h” type char signed char unsigned char short [int] unsigned short int unsigned int long [int] unsigned long format %c %c %c %hi %hu %i %u %li %lu bytes 1 1 1 2 2 2 or 4 2 or 4 4 4 minimum CHAR_MIN SCHAR_MIN maximum CHAR_MAX SCHAR_MAX UCHAR_MAX SHRT_MAX USHRT_MAX INT_MAX UINT_MAX LONG_MAX ULONG_MAX 0 SHRT_MIN 0 INT_MIN 0 LONG_MIN 0 .Integer Types in C  C supports different kinds of integers  maxima and minima defined in “limits.

h> int main(void) int main(void) { { unsigned long unsigned long big = ULONG_MAX. UINT_MAX). maximum int = 32767 minimum int = -32768. printf("maximum int = %i\n". INT_MIN). printf("minimum int = %i. INT_MIN). printf("maximum long int = %li\n". LONG_MAX). printf("maximum int = %i\n". LONG_MAX). maximum int = 32767 maximum unsigned = 65535 maximum unsigned = 65535 maximum long int = 2147483647 maximum long int = 2147483647 maximum unsigned long = 4294967295 maximum unsigned long = 4294967295 .h> #include <limits. big). big = ULONG_MAX.Integer Example #include <stdio.h> #include <stdio. big). printf("maximum long int = %li\n". ".h> #include <limits. printf("maximum unsigned long = %lu\n". minimum int = -32768. } } return 0. return 0. ". INT_MAX). printf("maximum unsigned long = %lu\n". INT_MAX). printf("minimum int = %i. printf("maximum unsigned = %u\n". printf("maximum unsigned = %u\n". UINT_MAX).

} } return 0. lower_a + 1). lower_a + 1).'a' + 'A').h> #include <limits. printf("after '%c' comes '%c'\n".h> #include <limits. CHAR_MIN). printf("uppercase is '%c'\n". printf("after '%c' comes '%c'\n".Character Example Note: print integer value of character #include <stdio. maximum char = 255 minimum char = 0. ". printf("uppercase is '%c'\n". printf("maximum char = %i\n". lower_m . printf("maximum char = %i\n". printf("minimum char = %i. lower_m . printf("minimum char = %i. CHAR_MAX). lower_a. char lower_m = 'm'.'a' + 'A'). lower_a. char lower_a = 'a'. ".h> #include <stdio. char lower_m = 'm'. CHAR_MAX). return 0. minimum char = 0. CHAR_MIN). maximum char = 255 after 'a' comes 'b' after 'a' comes 'b' uppercase is 'M' uppercase is 'M' .h> int main(void) int main(void) { { char lower_a = 'a'.

printf("dec=%d. hex). hex). hex=%d\n". hex = 0x20. oct. hex=%x\n". hex=20 . oct=%o. hex=%x\n". oct. hex). dec. oct. oct=20. dec. hex = 0x20. hex=%d\n". hex=20 dec=20. oct = 020. oct=20. dec=20.h> #include <stdio. dec. dec = 20. oct=16. } } return 0. printf("dec=%d. dec. return 0.Integers With Different Bases  It is possible to work in octal (base 8) and hexadecimal (base 16) zero puts compiler into octal mode! #include <stdio. zero “x” puts compiler into hexadecimal mode printf("dec=%d. oct=%d. oct=%o. oct=%d. oct. hex=32 dec=20. hex). hex=32 dec=20.h> int main(void) int main(void) { { int int dec = 20. oct=16. oct = 020. printf("dec=%d.

h” type float double long double format %f %e %g %lf %le %lg %Lf %Le %Lg bytes 4 8 10 minimum FLT_MIN DBL_MIN LDBL_MIN maximum FLT_MAX DBL_MAX LDBL_MAX .Real Types In C  C supports different kinds of reals  maxima and minima are defined in “float.

f.141600e+00 f=3. printf("f=%le\tg=%le\th=%le\n". printf("f=%lg\tg=%lg\th=%lg\n".2e-05 g=1.000000e+09 h=5e+09 h=5e+09 h=5e+09 h=5e+09 . double f = 3. h = 5000000000.2le\th=%. h). g. g.2e-5. f=3.000000 h=5. g.200000e-05 g=1. f.20e-05 h=5000000000. g.h> #include <float. printf("f=%lf\tg=%lf\th=%lf\n". f.000000e+09 h=5. printf("f=%lf\tg=%lf\th=%lf\n".h> int main(void) int main(void) { { double f = 3.14 3.1416.4lg\n".14 g=0. f.000012 g=0.h> #include <stdio. h).20e-05 g=1.141600e+00 f=3.2e-5.2le\th=%. h).141600 f=3.1416 f= f= 3. g. f. g = 1.0. g. h).000012 g=1.2lf\tg=%. h = 5000000000.2lf\tg=%. g. f. printf("f=%lg\tg=%lg\th=%lg\n".0. g = 1. h).2e-05 g=1. printf("f=%7.000000 h=5000000000. printf("f=%le\tg=%le\th=%le\n". h). f. return 0.4lg\n".1416. f. h).Real Example #include <stdio.200000e-05 g=1. h). g.141600 f=3. } } return 0.h> #include <float. printf("f=%7.1416 f=3.

e. 1e-7. -35 (some compilers switch to long int if the constant would overflow int)  For long int constants append “L”.”.” or “e” are double: 3. 10000.g. “e” or “F” are int.g.5F.29e15L. e.29e15  For float constants append “F”: 3.5. 9000000L . 1e-7F  For long double constants append “L”: -1.Constants  Constants have types in C  Numbers containing “. -1. 1e-7L  Numbers without “.

g). double g = 5000000000.” constant is int or long but 2. g). double g = 5000000000.000000 f=5000000000. printf("g=%lf\n". f).h> #include <stdio.000000 OVERFLOW double constant created because of “. double f = 5000000000. printf("f=%lf\n".483. } } return 0. f).0. printf("g=%lf\n".Warning! #include <stdio.147. f=5000000000.h> int main(void) int main(void) { { double f = 5000000000. return 0.0.000000 g=705032704.647 is the maximum! . printf("f=%lf\n".000000 g=705032704.

Named Constants
 Named constants may be created using const
creates an integer constant #include <stdio.h> #include <stdio.h> int main(void) int main(void) { { const long double pi = 3.141592653590L; const long double pi = 3.141592653590L; const int days_in_week = 7; const int days_in_week = 7; const sunday = 0; const sunday = 0; days_in_week = 5; days_in_week = 5; } } return 0; return 0;

error!

Preprocessor Constants
 Named constants may also be created using the Preprocessor
– Needs to be in “search and replace” mode – Historically these constants consist of capital letters
search for “PI”, replace with 3.1415.... Note: no “=” and no “;” 3.141592653590L 3.141592653590L 7 7 0 0

#include <stdio.h> #include <stdio.h> #define #define #define #define #define #define int int long long PI PI DAYS_IN_WEEK DAYS_IN_WEEK SUNDAY SUNDAY

day = SUNDAY; day = SUNDAY; flag = USE_API; flag = USE_API; “PI” is NOT substituted here

Take Care With printf And scanf!
#include <stdio.h> #include <stdio.h> int main(void) int main(void) { { short a = 256, b = 10; short a = 256, b = 10; printf("Type a number: "); printf("Type a number: "); scanf("%c", &a); scanf("%c", &a); printf("a = %hi, b = %f\n", a, b); printf("a = %hi, b = %f\n", a, b); } } return 0; return 0; Type a number: 1 Type a number: 1 a = 305 b = Floating support not loaded a = 305 b = Floating support not loaded

“%c” fills one byte of “a” which is two bytes in size

“%f” expects 4 byte float in IEEE format, “b” is 2 bytes and NOT in IEEE format

Summary
         K&R C vs Standard C main, printf Variables Integer types Real types Constants Named constants Preprocessor constants Take care with printf and scanf

Operators in C         Arithmetic operators Cast operator Increment and Decrement Bitwise operators Comparison operators Assignment operators sizeof operator Conditional expression operator .

Arithmetic Operators  C supports the arithmetic operators: + * / % addition subtraction multiplication division modulo (remainder)  “%” may not be used with reals .

g = 4.0. 1. h = f / g. h = i / j.0. 1 is assigned to “k” “f” and “g” are double. } } return 0. . return 0.00000 int main(void) int main(void) { { int i = 5. k = i / j. g = 4. integer division is done. h. h = i / j.25 is assigned to “h” integer division is still done. h. k. j = 4. Value assigned is 1. int i = 5. k.Using Arithmetic Operators  The compiler uses the types of the operands to determine how the calculation should be done “i” and “j” are ints. k = i / j. double division is done. j = 4.0. h = f / g. double f = 5.0. double f = 5. despite “h” being double.

double f. the result. f = (double)i / j. the other is automatically promoted int main(void) int main(void) { { int i = 5. is changed to a double. integer division is done here. j = 4. f = i / (double)j.00000 } } return 0. return 0. . f = (double)(i / j). f = (double)i / (double)j. 1. 1. double f. f = i / (double)j. f = (double)i / j. int i = 5. j = 4.The Cast Operator  The cast operator temporarily changes the type of a variable if either operand is a double. f = (double)(i / j). f = (double)i / (double)j.

i = 5. ++i. ++i. --j. i = 5. j = 4. j = 4. --j. .Increment and Decrement  C has two special operators for adding and subtracting one from a variable ++ -increment decrement  These may be either prefix (before the variable) or postfix (after the variable): “i” becomes 6 “j” becomes 3 “i” becomes 7 int int i++. i++.

i = j++.h> int main(void) int main(void) { { int i. . j). j=%d\n".Prefix and Postfix  The prefix and postfix versions are different #include <stdio. j = 5. j = 5. j=6 i=5. printf("i=%d. j=6 equivalent to: 1. i = j. i = ++j. j=%d\n". i. j). j=%d\n". i = j++. printf("i=%d. printf("i=%d. j). printf("i=%d. j++. i. j = 5. j++. 2. j=%d\n". j). i. } } return 0. i=6. return 0. i = j. int i. 2. i. j=6 i=6. j = 5. j=6 i=5.h> #include <stdio. i = ++j. equivalent to: 1.

integers are used instead  The value of 0 (or 0. 1. is true if(32) if(32) printf("this will always be printed\n"). -1.0) is false  Any other value. if(0) if(0) printf("this will never be printed\n").8. -20. greater than. etc.) and the logical operators (and. 0. printf("this will never be printed\n"). printf("this will always be printed\n"). or. not) it is important to understand how C regards truth  There is no boolean data type in C.3.Truth in C  To understand C’s comparison operators (less than. .

true) when the comparison succeeds and 0 (i.e. i.e. false) when the comparison fails .Comparison Operators  C supports the comparison operators: < <= > >= == != less than less than or equal to greater than greater than or equal to is equal to is not equal to  These all give 1 (non zero value.

k = 28. j = 10. true) when the condition succeeds and 0 (i. .Logical Operators  C supports the logical operators: && || ! and or not  These also give 1 (non zero value. i = ((j > 5) && (k < 100)) || (k > 24). i = ((j > 5) && (k < 100)) || (k > 24). i. j = 10. false) when the condition fails int int i. i. k = 28.e.e.

a[i]). a[i]). if false the whole statement is false (because false AND anything is false) thus “a[i] > 0” would not be evaluated if(i < 10 && a[i] > 0) if(i < 10 && a[i] > 0) printf("%i\n". printf("%i\n". .Logical Operator Guarantees  C makes two important guarantees about the evaluation of conditions  Evaluation is left to right  Evaluation is “short circuit” “i < 10” is evaluated first.

if(!i == 5) if(!i == 5) printf("i is not equal to five\n"). “!i” must be false.e. i is equal to five i is equal to five . i. i = 10.Warning!  Remember to use parentheses with conditions. true. otherwise your program may not mean what you think in this attempt to say “i not equal to five”.e. “!i” is evaluated first. i. Zero is compared with five int int i = 10. printf("i is equal to five\n"). zero. i. As “i” is 10.e. else else printf("i is equal to five\n"). non zero. printf("i is not equal to five\n").

Bitwise Operators  C has the following bit operators which may only be applied to integer types: & | ^ ~ >> << bitwise and bitwise inclusive or bitwise exclusive or one’s compliment right shift left shift .

unsigned short c = 7097. short a = 0x6eb9. a & b). printf("0x%x\n". ". a ^ b). ". a | b). return 0.h> int main(void) int main(void) { { short a = 0x6eb9. printf("0x%x. ". 0x339e 0x4c21. 3548 0x6eb9 0110 1110 1011 1001 0x6eb9 0110 1110 1011 1001 0x5d27 0101 1101 0010 0111 0x5d27 0101 1101 0010 0111 0x4c21 0100 1100 0010 0001 0x4c21 0100 1100 0010 0001 0x6eb9 0110 1110 1011 1001 0x6eb9 0110 1110 1011 1001 0x5d27 0101 1101 0010 0111 0x5d27 0101 1101 0010 0111 0x7fbf 0111 1111 1011 1111 0x7fbf 0111 1111 1011 1111 0x6eb9 0110 1110 1011 1001 0x6eb9 0110 1110 1011 1001 0x5d27 0101 1101 0010 0111 0x5d27 0101 1101 0010 0111 0x339e 0011 0011 1001 1110 0x339e 0011 0011 1001 1110 7097 0001 1011 1011 1001 7097 0001 1011 1011 1001 28388 0110 1110 1110 0100 28388 0110 1110 1110 0100 7097 0001 1011 1011 1001 7097 0001 1011 1011 1001 3548 0000 1101 1101 1100 3548 0000 1101 1101 1100 . a & b). ". printf("%u\n".h> #include <stdio.Bitwise Example #include <stdio. c >> 1). c >> 1). ". printf("0x%x. unsigned short c = 7097. short b = 0x5d27. a | b). 0x7fbf. short b = 0x5d27. printf("%u. c << 2). printf("%u\n". a ^ b). } } return 0. c << 2). 0x4c21. printf("%u. ". printf("0x%x. 0x339e 28388. printf("0x%x. 3548 28388. printf("0x%x\n". 0x7fbf.

j = 93). printf("%i\n". n. l. j. Assigning 22 to “m” makes 22 available for assignment to “l” etc. m. this makes 22 available for assignment to “m”. int i. the 93 is then made available to printf for printing .Assignment  Assignment is more flexible than might first appear  An assigned value is always made available for subsequent use “n = 22” happens first. l. int i. n. k. “j” is assigned 93. i = j = k = l = m = n = 22. k. j = 93). printf("%i\n". j. i = j = k = l = m = n = 22. m.

if(i = 0) if(i = 0) printf("i is equal to zero\n").Warning!  One of the most frequent mistakes is to confuse test for equality. } } return 0. return 0. somehow i is not zero somehow i is not zero . i = 0. with assignment. “=” #include <stdio. else else printf("somehow i is not zero\n"). printf("somehow i is not zero\n"). “==”. printf("i is equal to zero\n").h> #include <stdio.h> int main(void) int main(void) { { int int i = 0.

i = i * (j + 2). i = i * (j + 2). f /= 9.2. f /= 9. a = a + 27. f = f / 9. a += 27. i *= j + 2.2.Other Assignment Operators  There is a family of assignment operators: += &= <<= -= |= >>= *= ^= /= %=  In each of these: expression1 op= expression2 is equivalent to: (expression1) = (expression1) op (expression2) a += 27. i *= j + 2. f = f / 9.2. a = a + 27. .2.

printf("\"big\" is %u bytes\n". sizeof(big)). printf("\"big\" is %u bytes\n". } } return 0. return 0. "big" is 4 bytes "big" is 4 bytes a short is 2 bytes a short is 2 bytes a double is 8 bytes a double is 8 bytes . printf("a short is %u bytes\n". sizeof(big)). printf("a double is %u bytes\n". printf("a double is %u bytes\n". sizeof double).sizeof Operator  C has a mechanism for determining how many bytes a variable occupies #include <stdio. long big.h> #include <stdio. printf("a short is %u bytes\n".h> int main(void) int main(void) { { long big. sizeof(short)). sizeof(short)). sizeof double).

i = (j > k) ? j : k. int i. k = -1. j = 100. the third is evaluated int i. i = (j < k) ? j : k. j = 100. the second is evaluated  If the first expression is false. . j = 100. int i. i = j. i = k. else else i = k. i = j. int i. else else i = k. i = k. if(j < k) if(j < k) i = j. k = -1. i = (j < k) ? j : k. k = -1. k = -1. i = (j > k) ? j : k. j = 100.Conditional Expression Operator  The conditional expression operator provides an in-line if/then/else  If the first expression is true. if(j > k) if(j > k) i = j.

j = 18 j = 18 } } .h> #include <stdio. return 0. printf("j = %i\n".h> int main(void) int main(void) { { int j = 3 * 4 + 48 / 7. return 0. printf("j = %i\n". j).Precedence of Operators  C treats operators with different importance. known as precedence  There are 15 levels  In general. the unary operators have higher precedence than binary operators  Parentheses can always be used to improve clarity #include <stdio. j). int j = 3 * 4 + 48 / 7.

i). return 0.e.h> #include <stdio. printf("i = %d\n". printf("i = %d\n". is used  Associativity is either “left to right” (left operator first) or “right to left” (right operator first) #include <stdio.Associativity of Operators  For two operators of equal precedence (i. i = 3 i = 3 . } } return 0. “associativity”.h> int main(void) int main(void) { { int i = 6 * 4 / 7. same importance) a second rule. i). int i = 6 * 4 / 7.

.+ (cast) * & sizeof * / % + << >> < <= >= > == != & | ^ && || ?: = += -= *= /= %= etc . Associativity left to right right to left left to right left to right left to right left to right left to right left to right left to right left to right left to right left to right right to left right to left left to right . ! ~ ++ -.Precedence/Associativity Table Operator () [] -> .

Review #include <stdio. j). printf("j = %d\n". j = i == 0 & k. j. . m = 5. j = k++ > 7. j). n). printf("j = %d\n". k = 7. printf("j = %d\n". n. int i = 0. j). j). printf("n = %d\n". printf("j = %d\n". n = !i > k >> 2.h> int main(void) int main(void) { { int i = 0. j. j = k++ > 7. printf("n = %d\n". n = !i > k >> 2. return 0. n). m = 5. k = 7. printf("j = %d\n".h> #include <stdio. n. printf("j = %d\n". j). } } return 0. j = i == 0 & k. j = m += 2. j). j = m += 2.

for Keyword break Keyword continue .switch Loops .Control Flow      Decisions .while.if then else More decisions . do while.

if(i > 0) if(i > 0) printf("a positive number was entered\n"). i = -i. &i). &i). printf("a positive number was entered\n").Decisions . i = -i. scanf("%i".if then  Parentheses surround the test  One statement becomes the “then part”  If more are required. braces must be used scanf("%i". } } . if(i < 0) { if(i < 0) { printf("a negative number was entered\n"). printf("a negative number was entered\n").

if(j > 0). &j). scanf("%i". if(j > 0).Warning!  A semicolon after the condition forms a “do nothing” statement printf("input an integer: "). input an integer: -6 input an integer: -6 a positive number was entered a positive number was entered . printf("a positive number was entered\n"). &j). printf("input an integer: "). scanf("%i". printf("a positive number was entered\n").

if more are required. printf("i is positive\n"). i = -i. } } . braces must be used if(i > 0) if(i > 0) printf("i is positive\n"). else { else { printf("i is negative\n"). printf("i is negative\n"). if(i > 0) if(i > 0) printf("i is positive\n"). printf("i is negative\n"). else else printf("i is negative\n"). printf("i is positive\n"). i = -i.if then else  An optional else may be added  One statement by default.

Nesting ifs  else associates with the nearest if int i = 100. printf("i is big\n"). } else i is negative } else i is negative printf("i is negative\n"). printf("i is big\n"). i is reasonable int i = -20. else else printf("i is reasonable\n"). i is reasonable printf("i is reasonable\n"). int i = -20. if(i > 0) { if(i > 0) { if(i > 1000) if(i > 1000) printf("i is big\n"). printf("i is negative\n"). . int i = 100. if(i > 0) if(i > 0) if(i > 1000) if(i > 1000) printf("i is big\n").

2f\n". break. break. break. 2 * r * pi). printf("area = %. break. break.2f\n". } } . r * r * pi). break. break. printf("circumference = %. printf("quit option chosen\n").switch  C supports a switch for multi-way decision making switch(c) { switch(c) { case 'a': case 'A': case 'a': case 'A': printf("area = %. printf("unknown option chosen\n").2f\n". break. default: default: printf("unknown option chosen\n"). r * r * pi). case 'q': case 'q': printf("quit option chosen\n"). 2 * r * pi). case 'c': case 'C': case 'c': case 'C': printf("circumference = %.2f\n".

. ... case 1: printf("i = 1\n").. . switch(i) { switch(i) { case 2 * j: case 2 * j: .... case 1: printf("i = 1\n"). i = 3..More About switch     Only integral constants may be tested If no condition matches. the default is executed If no default.. case 3: printf("i = 3\n"). nothing is done (not an error) The break is important float f. case 2: printf("i = 2\n"). switch(i) { switch(i) { case 3: printf("i = 3\n"). case 2: printf("i = 2\n"). switch(f) { switch(f) { case 2: case 2: .... float f. i = 3. } } i = 3 i = 3 i = 2 i = 2 i = 1 i = 1 .

"). case 9: printf("nine drummers drumming. case 2: printf("2nd"). "). break. case 8: printf("eight maids aa milking. i). default: printf("%ith". case 6: printf("six geese laying. "). break. "). case 2: printf("two turtle doves and "). "). case 2: printf("2nd"). i). "). "). printf("On the "). case 7: printf("seven swans swimming. "). break. break. }} printf(" day of Christmas my true love sent to me "). case 2: printf("two turtle doves and "). case 7: printf("seven swans aa swimming. switch(i) {{ switch(i) case 1: printf("1st"). case 1: printf("1st"). "). ").A switch Example printf("On the "). "). "). case 10: printf("ten pipers piping. break. case 3: printf("three French hens. break. case 5: printf("five gold rings. default: printf("%ith". case 9: printf("nine drummers drumming. case 11: printf("eleven ladies dancing. case 8: printf("eight maids milking. "). case 4: printf("four calling birds. break. }} . "). case 3: printf("three French hens. "). switch(i) {{ switch(i) case 12: printf("twelve lords aa leaping. "). "). case 6: printf("six geese aa laying. printf(" day of Christmas my true love sent to me "). case 12: printf("twelve lords leaping. "). case 11: printf("eleven ladies dancing. "). case 1: printf("a partridge in pear tree\n"). break. case 1: printf("a partridge in aa pear tree\n"). case 5: printf("five gold rings. case 4: printf("four calling birds. case 3: printf("3rd"). case 3: printf("3rd"). case 10: printf("ten pipers piping. ").

j). } } j = 5 j = 5 j = 4 j = 4 j = 3 j = 3 j = 2 j = 2 j = 1 j = 1 . j).while Loop     The simplest C loop is the while Parentheses must surround the condition One statement forms the body of the loop Braces must be added if more statements are to be executed int j = 5. printf("j = %i\n". j--. while(j > 0) while(j > 0) printf("j = %i\n". printf("j = %i\n". while(j > 0) { while(j > 0) { printf("j = %i\n". int j = 5. j--). j--). j--.

j.(Another) Semicolon Warning!  A semicolon placed after the condition forms a body that does nothing int j = 5. j--). j--). int c. int j = 5. while(scanf("%i". j. printf("j = %i\n". while(j > 0). printf("j = %i\n". &j) != 1) while((c = getchar()) != '\n') while((c = getchar()) != '\n') . program disappears into an infinite loop • Sometimes an empty loop body is required int c. . placing semicolon on the line below makes the intention obvious . while(j > 0). &j) != 1) while(scanf("%i".

printf("end\n"). int j = 5. printf("start\n"). j--).while. printf("j = %i\n". printf("end\n"). start start end end user probably intends “until j is equal to zero”. Not Until!  Remember to get the condition the right way around! int j = 5. while(j == 0) while(j == 0) printf("j = %i\n". j--). however this is NOT the way to write it . printf("start\n").

int j = 5. printf("start\n"). printf("start\n"). printf("j = %i\n". int j = -10. do do printf("j = %i\n". start start j = 5 j = 5 j = 4 j = 4 j = 3 j = 3 j = 2 j = 2 j = 1 j = 1 stop stop start start j = -10 j = -10 stop stop .do while  do while guarantees execution at least once int j = 5. j--). printf("start\n"). printf("start\n"). int j = -10. printf("j = %i\n". j). j--. printf("stop\n"). printf("stop\n"). do { do { printf("j = %i\n". j--). printf("stop\n"). while(j > 0). printf("stop\n"). } while(j > 0). while(j > 0). } while(j > 0). j). j--.

while-condition. j). j). j > 0. ((j%2)==0)?"even":"odd"). j). j).for Loop  for encapsulates the essential elements of a loop into one statement for(initial-part. int j. j = 5 j = 5 int j. j--) printf("j = %i\n". body. j > 0. j--) { printf("j = %i ". ((j%2)==0)?"even":"odd"). j > 0. j = 4 j = 4 j = 3 for(j = 5. } } j = 5 odd j = 5 odd j = 4 even j = 4 even j = 3 odd j = 3 odd j = 2 even j = 2 even j = 1 odd j = 1 odd . update-part) body. j--) { for(j = 5. while-condition. printf("%s\n". j--) j = 3 for(j = 5. j = 2 j = 1 j = 1 for(j = 5. printf("j = %i ". update-part) for(initial-part. j = 2 printf("j = %i\n". printf("%s\n". j > 0.

printf("end\n").for Is Not Until Either!  Remember to get the for condition the right way around (it is really a while condition) int j. j == 0. for(j = 5. j). j--) for(j = 5. printf("j = %i\n". j--) printf("j = %i\n". j). printf("start\n"). int j. start start end end . user probably intends “until j is equal to zero”. printf("end\n"). however this is NOT the way to write it either! printf("start\n"). j == 0.

h> #include <math. angle += 0. return 0. angle. . angle < 3. sin(angle)).h> int main(void) int main(void) { { double angle. for(angle = 0. sin(angle)).2) printf("sine of %. double angle. printf("sine of %.2lf\n".2) for(angle = 0. angle < 3.0.1lf is %. angle.0.14159.14159. } } return 0.2lf\n".1lf is %. the for loop is not restricted to stepping up or down by 1 #include <math. angle += 0.Stepping With for  Unlike some languages.

) for(. k = -1.. i < 10. j = 5. j.i < 10. i++.) for(. k. i < 10. k--) for(i = 0. j++. k = -1. j++.) for(.Extending the for Loop  The initial and update parts may contain multiple comma separated statements int i. int i. k--) for(. for(i = 0. i++. j. k. i < 10.i < 10.) use of a while loop would be clearer here! creates an infinite loop . i++. j++. i < 10.. condition and update parts may contain no statements at all! for(. j = 5. k--) for(. i++. j++. k--)  The initial.

printf("type an int: "). j). if(scanf("%i". break.) { for(. } } type an int: an int type an int: an int printf("j = %i\n". type an int: no type an int: no type an int: 16 type an int: 16 j = 16 j = 16 . j). &j) == 1) break. printf("j = %i\n". &j) == 1) if(scanf("%i".break  The break keyword forces immediate exit from the nearest enclosing loop  Use in moderation! if scanf returns 1. while((c = getchar()) != '\n') while((c = getchar()) != '\n') .) { printf("type an int: ")... . jump out of the loop for(.

j++) { for(j = 1. j). printf("j = %i\n". continue. j++) { if(j % 3 == 0) if(j % 3 == 0) continue. } } j = 1 j = 1 j = 2 j = 2 j = 4 j = 4 j = 5 j = 5 j = 7 j = 7 j = 8 j = 8 j = 10 j = 10 . skip for(j = 1. j). j <= 10.continue  The continue keyword forces the next iteration of the nearest enclosing loop  Use in moderation! if j is exactly divisible by 3. printf("j = %i\n". j <= 10.

watch the semicolons again  break  continue .Summary  if (then) else . do while.watch the semicolons  switch can test integer values  while. for .

Functions        Rules of functions Examples .writing a function. calling a function Function prototypes Visibility Call by value The stack auto. static and register .

unless explicitly passed to another function . or no parameters (like main)  A function may return either one or no values  Variables declared inside a function are only available to that function.The Rules  A function may accept as many parameters as it needs.

lines++) for(d = start. } } return lines.1lf\n". d <= end.1lf\n".8 + 32). printf("Celsius\tFarenheit\n"). d += step. d += step. return lines. d * 1. d. d * 1. double end. d.1lf\t%. double end. d <= end. this is the ACTUAL value handed back .8 + 32). int lines = 1. printf("%.Example this is the TYPE of the value handed back accept 3 doubles when called int print_table(double start. printf("Celsius\tFarenheit\n"). lines++) printf("%.Writing a Function . double step) int print_table(double start.1lf\t%. int lines = 1. for(d = start. double step) { { double double d. d.

end. 200.Example IMPORTANT: this tells the compiler how print_table works #include <stdio.this is ok. } } return 0. how_many = print_table(1. double.0. the compiler knows these should be doubles and converts them automatically here the function’s return value is ignored .Calling a Function . 15). if you don’t want it. 3). 3). int how_many.h> int print_table(double. end. double end = 100. double). 15).0. int main(void) int main(void) { { int how_many.0. print_table(end. return 0. double).h> #include <stdio. double. double end = 100. how_many = print_table(1. int print_table(double. 200. you don’t have to use it .0. print_table(end.

double double end = 100. The function picks up doubles anyway! . the compiler does NOT convert these ints to doubles. 200.0.0.Calling a Function . 3). int how_many.0. 3). } } return 0. end. end = 100.h> #include <stdio.h> int main(void) int main(void) { { int how_many. print_table(end. 200. print_table(end. how_many = print_table(1.Disaster! now the compiler does not know how the function works #include <stdio. 15). 15). how_many = print_table(1.0. return 0. end.

double. is known as a prototype  If the compiler meets a call to an unknown function it “guesses” – Guess 1: the function returns an int. even if it doesn’t – Guess 2: you have passed the correct number of parameters and made sure they are all of the correct type.Prototypes  The (optional) line int print_table(double. double). even if you haven’t  The prototype provides the compiler with important information about the return type and parameters .

write a prototype by hand . #include the file specified in the help page(s) this file will contain the prototype  When calling one of your own functions.Prototyping is Not Optional  To achieve working programs the compiler is best given a prototype for each function called  When calling a Standard Library function.

Writing Prototypes  Prototype: int print_table(double. double end. int print_table(double start. double z). double end. int print_table(double.  Function header: int print_table(double start. double). int print_table(double x. double step). double z). double step) { {  The function prototype may optionally include variable names (which are ignored) int print_table(double start. double end. double step) int print_table(double start. double step). double. double y. double). int print_table(double x. double y. double. double end. .

double end. double step). double step) int print_table(double start. {{ . double end. double end.  The function header has an open brace int print_table(double start. int print_table(double start. double end. int print_table(double start. double step). double step).Take Care With Semicolons  The prototype has a semicolon int print_table(double start. double end. double step) {{  Don’t confuse the compiler by adding a semicolon into the function header! int print_table(double start. double step). double end.

int year). double return value */ double k_and_r_function(). int month. /* no parameters. (default) int return value */ transfer(short int s). int month. int return value */ /* three int parameters. /* short int parameter. (default) int return value */ /* short int parameter. no return value */ void clear_screen(void). double k_and_r_function(). int. void clear_screen(void). int). long int return value */ /* three int parameters. int. int get_integer(void). int return value */ int get_integer(void). int year). int). . /* parameter checking DISABLED. double return value */ double get_double(void). long int return value */ long day_since_1_jan_1970(int.Example Prototypes /* no parameters. double get_double(void). int return value */ int day_of_year(int day. transfer(short int s). /* three int parameters. /* three int parameters. long day_since_1_jan_1970(int. double return value */ /* no parameters. int day_of_year(int day. int return value */ /* no parameters. no return value */ /* no parameters. /* no parameters. double return value */ /* parameter checking DISABLED.

i = transfer(s).7). i = transfer(s). l = day_since_1_jan_1970(1. 7. d = k_and_r_function(19. 4. the compiler cannot tell which of these (if any) is correct . d = k_and_r_function("hello world"). l. i = get_integer(). 1969). d = k_and_r_function(). d = k_and_r_function().Example Calls int int double double long long short int short int i. clear_screen(). l = day_since_1_jan_1970(1. i = day_of_year(16. 1983). i = get_integer(). i = day_of_year(16. d = k_and_r_function("hello world"). d. d = get_double().7). i. d = k_and_r_function(19. l. d = get_double(). 1969). s = 5. clear_screen(). 1983). 4.neither can we without resorting to documentation! no mention of “void” when calling these functions . d. 7. s = 5.

not main’s } } . d = 3. float f = 2.Rules of Visibility  C is a block structured language. “i” and “g” not available here func’s “f” is used. compiler does not know about “d” } } void func(int v) void func(int v) { { double d. g--. g--. i++. variables may only be used in functions declaring them int int { { main(void) main(void) int i = 5.8F. k = 2. f. double d.8F. j. f = 0. int i = 5. f. e = 0.0.7.7. d = 3. g. f = 0. j. e = 0. g. float f = 2. k = 2. i++.0.0.0.

Call by Value  When a function is called the parameters are copied .“call by value”  The function is unable to change any variable passed as a parameter  In the next chapter pointers are discussed which allow “call by reference”  We have already had a sneak preview of this mechanism with scanf .

printf("main: var = %i\n". printf("change: v = %i\n". v). void change(int v). } } the function is able to alter “v” change: v = 500 change: v = 500 main: var = 5 main: var = 5 . v). printf("main: var = %i\n". change(var). int int { { main(void) main(void) int var = 5. int var = 5.h> #include <stdio. change(var).Example #include <stdio. v *= 100. var). return 0. the function was not able to alter “var” } } void change(int v) void change(int v) { { v *= 100. var). return 0.Call by Value . printf("change: v = %i\n".h> void change(int v).

the called function pops its local variables and jumps back to the calling function  The calling function pops the parameters  The return value is handled .C and the Stack  C uses a stack to store local variables (i.e. it is also used when passing parameters to functions  The calling function pushes the parameters  The function is called  The called function picks up the parameters  The called function pushes its local variables  When finished. those declared in functions).

0 2 5 ? 2 power: result power: n power: p main: d main: x . } } double power(int n. return 0. return result. double d. result *= n. printf("%lf\n". int main(void) int main(void) { { int x = 2.Stack Example #include <stdio. double result = n. return 0. d). int x = 2. double power(int.h> double power(int. int p) { { double result = n. 5). } } return result. printf("%lf\n". 5). 32. d = power(x. int p) double power(int n. int). d). while(--p > 0) while(--p > 0) result *= n. double d.h> #include <stdio. int). d = power(x.

place in the data segment register .Storage  C stores local variables on the stack  Global variables may be declared.place on the stack (default) static . These are not stack based.place in a CPU register  Data may also be placed on the heap. this will be discussed in a later chapter . but are placed in the data segment  Special keywords exist to specify where local variables are stored: auto .

auto int columns. auto keyword redundant . a function  These variables are therefore called “automatic”  Initial value: random  Initialisation: recommended int table(void) int table(void) { { int lines = 13. and automatically deallocated on exit from. auto int columns.auto  Local variables are automatically allocated on entry into. int lines = 13.

but local to this function .static  The static keyword instructs the compiler to place a variable into the data segment  The data segment is permanent (static)  A value left in a static in one call to a function will still be there at the next call  Initial value: 0  Initialisation: unnecessary if you like zeros int running_total(void) int running_total(void) { { static int rows. static int rows. rows++. rows++. permanently allocated.

register  The register keyword tells the compiler to place a variable into a CPU register (you cannot specify which)  If a register is unavailable the request will be ignored  Largely redundant with optimising compilers  Initial value: random  Initialisation: recommended void speedy_function(void) void speedy_function(void) { { register int i. for(i = 0. i < 10000. i < 10000. i++) for(i = 0. i++) . register int i.

variable “d” is global and available to all functions defined below it . int i.Global Variables  Global variables are created by placing the declaration outside all functions  They are placed in the data segment  Initial value: 0  Initialisation: unnecessary if you like zeros #include <stdio. } } return 0. return 0.h> double d.h> #include <stdio. int main(void) int main(void) { { int i. double d.

this can be changed with the static and register keywords  Global variables may be created. they are stored in the data segment      .Review Writing and calling functions The need for function prototypes Visibility C is “call by value” Local variables are stack based.

Pointers        Declaring pointers The “&” operator The “*” operator Initialising pointers Type mismatches Call by reference Pointers to pointers .

– Put data onto the heap – Create tables of functions for handling Windows events. trees. write functions which change their parameters) – Handle arrays efficiently – Handle structures (records) efficiently – Create linked lists.Why?  Using pointers allows us to: – Achieve call by reference (i.Pointers .  Already been using pointers with scanf  Care must be taken when using pointers since there are no safety features . graphs etc. signals etc.e.

. p.  There is some debate as to the best position of the “*” int* int* p.  Declare a pointer to an integer: int int *p.Declaring Pointers  Pointers are declared by using “*”  Declare an integer: int int i. i. *p.

start. *pc. pd. c. *p. pd. e. end.Example Pointer Declarations int int long int long int float* float* char char double* double* char* char* char* char* *pi. e. f. d. /* pi is a pointer to an int */ /* pi is a pointer to an int */ /* p is a pointer to a long int */ /* p is a pointer to a long int */ /* pf is a pointer to a float */ /* pf is a pointer to a float */ /* c and d are a char /* c and d are a char pc is a pointer to char */ pc is a pointer to char */ /* pd is pointer to a double /* pd is pointer to a double e and f are double */ e and f are double */ /* start is a pointer to a char */ /* start is a pointer to a char */ /* end is a pointer to a char */ /* end is a pointer to a char */ . *pi. pf. d. pf. start. f. *pc. c. *p. end.

generates the address of a variable  All variables have addresses except register variables char char int int { { g = 'z'.The “&” Operator  The “&”. g = 'z'. p 0x1132 p 0x91A2 0x91A2 0x1132 g 'z' c 'a' p = &c. p = &g. p = &g. . c = 'a'. *p. p = &c. “address of” operator. main(void) main(void) char char char char c = 'a'. *p. } } return 0. return 0.

/* large is a long int. p = &large. initialised with 27 */ initialised with 27 */ /* ERROR */ /* ERROR */ p = &large. short int or long int. large = 27L. .. large = 27L.. int int long long *p. *p. certainly not to char or any of the integers  Etc.. certainly not to float.Rules  Pointers may only point to variables of the same type as the pointer has been declared to point to  A pointer to an int may only point to an int – not to char... double or long double  A pointer to a double may only point to a double – not to float or long double. /* p is a pointer to an int */ /* p is a pointer to an int */ /* large is a long int.

*p). printf("%c\n".h> char g = 'z'. *p. printf("%c\n". } } return 0. p = &g. *p). “points to” operator. printf("%c\n".h> #include <stdio.The “*” Operator  The “*”. return 0. finds the value at the end of a pointer #include <stdio. *p). p 0x91A2 0x91A2 p 0x1132 0x1132 g 'z' c 'a' p = &c. *p. char g = 'z'. c = 'a'. a a z z print “what p points to” . int int { { main(void) main(void) char char char char c = 'a'. p = &g. *p). p = &c. printf("%c\n".

printf("%c\n". *p. *p). p = &c. p = &c. *p = 'b'. p = &c. *p). *p). printf("%c\n". printf("%c\n". *p. make what p points to equal to ‘b’ . c = 'a'. *p. *p). printf("%c\n". c = 'a'. c 0x1132 'a' 'b' 0x1132 p = &c. *p = 'b'.  It is possible to write over the value at the end of a pointer: p char char char char c = 'a'. *p.Writing Down Pointers  It is not only possible to read the values at the end of a pointer as with: char char char char c = 'a'.

short i = 13. } } return 0.h> #include <stdio. printf("%hi\n". p ? 0x1212 i 13 . *p).Initialisation Warning!  The following code contains a horrible error: #include <stdio. short *p. *p). short *p. return 0.h> int int { { main(void) main(void) short i = 13. *p = 23. printf("%hi\n". *p = 23.

i = 13. *p = &i. *p = &i.  This does NOT mean “make what p points to equal to the address of i”  It DOES mean “declare p as a pointer to a short int. make p equal to the address of i” short short *p = &i. *p = &i. .Initialise Pointers!  Pointers are best initialised!  A pointer may be declared and initialised in a single step short short short short i = 13. *p = &i. short short short short *p = &i. *p = &i. *p = &i.

NULL  A special invalid pointer value exists #defined in various header files. *p). return 0. or when found in a pointer. short *p = NULL. short i = 13. if(p == NULL) if(p == NULL) printf("the pointer is invalid!\n"). return 0. called NULL  When assigned to a pointer.h> int main(void) int main(void) { { short i = 13. short *p = NULL. it indicates the pointer is invalid #include <stdio. printf("the pointer is invalid!\n"). *p). printf("the pointer points to %hi\n". } } . else else printf("the pointer points to %hi\n".h> #include <stdio.

*p = &i. j = 14.A World of Difference!  There is a great deal of difference between: int int int int int int i = 10. *p = &i. i = 10. *p = *q. p 0x15A0 q 0x15A4 0x15A4 0x15A0 j 14 i 10 14 *p = *q. p = q. j = 14. *q = &j. j = 14. *p = &i. *q = &j. p 0x15A0 0x15A4 q 0x15A4 0x15A0 j 14 0x15A4 i 10 p = q. *q = &j. j = 14. and: int int int int int int i = 10. . *q = &j. i = 10. *p = &i.

k. return 0. *p = *q. int *p = &i. j = 14. int i = 10. p = &k. i 0x2100 j 0x2104 k 0x1208 p 0x120B q 0x1210 . } } return 0. *p += 1. p = q. j = 14.Fill in the Gaps int int { { main(void) main(void) int i = 10. *p += 1. *p = *q. *p = *q. p = q. int *q = &j. *p = *q. p = &k. int *q = &j. k. int *p = &i.

Type Mismatch  The compiler will not allow type mismatches when assigning to pointers. *q = &j. j = 14. *p = q. p = *q. cannot write 0x15A4 into i cannot write 14 into p . *p = q. *p = &i. *p = &i. q 0x15A4 0x15A4 0x15A0 j 14 i 10 p = *q. j = 14. *q = &j. i = 10. or to where pointers point p 0x15A0 int int int int int int i = 10.

var). printf("main: var = %i\n".h> void change(int v). printf("main: var = %i\n". v). v). } } the function is able to alter “v” change: v = 500 change: v = 500 main: var = 5 main: var = 5 . printf("change: v = %i\n". var). v *= 100.Call by Value .Reminder #include <stdio. return 0. return 0. change(var). int int { { main(void) main(void) int var = 5. int var = 5. printf("change: v = %i\n".h> #include <stdio. void change(int v). change(var). the function was not able to alter “var” } } void change(int v) void change(int v) { { v *= 100.

int int { { main(void) main(void) int var = 5. *p). } } change: *p = 500 change: *p = 500 main: var = 500 main: var = 500 . var). printf("main: var = %i\n". change(&var). printf("change: *p = %i\n". change(&var). printf("change: *p = %i\n". *p). printf("main: var = %i\n".h> #include <stdio.Call by Reference prototype “forces” us to pass a pointer #include <stdio. int var = 5. var). main: var 0x1120 change: p 5 } } 0x1120 void change(int* p) 0x1124 void change(int* p) { { *p *= 100. *p *= 100. return 0. return 0. void change(int* p).h> void change(int* p).

int **pp. **pp).Pointers to Pointers  C allows pointers to any type  It is possible to declare a pointer to a pointer #include <stdio. pp = &p.h> #include <stdio. } } return 0. int i = 16. **pp). printf("%i\n". return 0. printf("%i\n". int *p = &i. pp is a “pointer to” a “pointer to an int” i 0x2320 p 0x2324 pp 0x2328 16 0x2320 0x2324 .h> int int main(void) main(void) { { int i = 16. int *p = &i. int **pp. pp = &p.

*pp = &k. i j k p q **pp += 1. *q = &j. k. k. j = 7. *pp = &k. /* headache? */. *pp = &p. j = 7. **pp = *q. i = *q/**pp. *p = &i. pp . **pp += 1. i = *q/**pp. i = *q***pp. **pp = *q. i = *q***pp. i = 10. return 0.Review int int { { main(void) main(void) int int int int int int int int i = 10. *p = &i. *pp = &p. *q = &j. } } return 0. /* headache? */.

Arrays in C       Declaring arrays Accessing elements Passing arrays into functions Using pointers to access arrays Strings The null terminator .

for instance. is fixed forever .there is no equivalent of. the “redim” command in BASIC .Declaring Arrays  An array is a collection of data items (called elements) all of the same type  It is declared using a type. a variable name and a CONSTANT placed in square brackets  C always allocates the array in a single block of memory  The size of the array. once declared.

2. d[100] d[100] = { 1. 11. 13 }. big[100]. 3. 3. a[5] = { 10. 7. double d[c]. 5. short primes[].5. 2. 100 bytes */ /* 10 long doubles. 50 }. short primes[]. d[100]. double d[c]. first two elements initialised. 11. 100 bytes */ all five elements initialised a[5] = { 10. n[50] = { 0 }. = { 1. 50 }. 7. 5.7 }. 30. 10 10 /* a is an array of 5 ints */ /* a is an array of 5 ints */ /* big is 400 bytes! */ /* big is 400 bytes! */ /* but d is 800 bytes! */ /* but d is 800 bytes! */ /* 10 long doubles. v[SIZE]. d[100].5. int a[i]. int i = 7. 40. big[100]. primes[] = { 1. const int c = 5. int a[i]. 20. v[SIZE]. 13 }. remaining ones set to zero quickest way of setting ALL elements to zero . 20. const int c = 5. primes[] = { 1. a[5]. 2. n[50] = { 0 }. 2. 40. 30.Examples #define #define int int long int long int double double long double long double int int double double short short long long SIZE SIZE a[5]. compiler fixes size at 7 elements int i = 7.7 }.

a[0] = 59.. a[0] = 59. return 0. a[6] = 0. a[i/2] = 2. a 0 1 2 3 4 5 .size-1  There is no bounds checking int main(void) int main(void) { { int a[6]. a[5] = -10. } } return 0. int i = 7. a[i/2] = 2. a[-1] = 5. a[5] = -10. a[-1] = 5. int a[6]. int i = 7.Accessing Elements  The elements are accessed via an integer which ranges from 0. a[6] = 0.

thus a == &a[0] int int int int a[10]. float *fp. /* p = &a[0] */ /* p = &a[0] */ /* fp = &f[0] */ /* fp = &f[0] */ . *p. i. a[10]. *p. p fp a f float f[5] float f[5] float *fp. fp = f. fp = f.Array Names  There is a special and unusual property of array names in C  The name of an array is a pointer to the start of the array. the zeroth element. p = a.e. p = a.

int size) { { . or by using the following special syntax int add_elements(int a[]. int size) int add_elements(int a[].Passing Arrays to Functions  When an array is passed to a function a pointer to the zeroth element is passed across  The function may alter any element  The corresponding parameter may be declared as a pointer. int size) int add_elements(int *p. int size) { { int add_elements(int *p.

6). 3. int sz) {{ int int i. int). 11 }. long primes[6] 1. sum(primes. 5. sz.h> void sum(long []. i. primes[0]). int int {{ main(void) main(void) long primes[6] == {{ 1. i++) total += a[i].Example primes #include <stdio. 11 }.h> #include <stdio. a[0] total. 5. printf("%li\n". 2. }} for(i == 0. a[0] == total. 7. return 0. int). return 0. 2. primes[0]). long total == 0. 3. 1 2 3 5 7 11 a sz 6 }} void sum(long a[]. provides bounds checking the total is written over element zero . 7. void sum(long []. sum(primes. ii << sz. i++) for(i 0. long total 0. total += a[i]. 6). int sz) void sum(long a[]. printf("%li\n".

long *p.4. long *p. *p).6 }. printf("%ld\n". p += 4. *p). p = v. printf("%ld\n". printf("%ld\n". *p). p = v. p += 4 p++ p 1 1 2 2 6 6 1000 v 1 2 3 4 5 6 1016 1000 1008 1012 1020 1004 .2. 3.5.5.4. *p). long v[6] = { 1. p++.6 }. printf("%ld\n". printf("%ld\n". *p). 3. *p). p++.Using Pointers  Pointers may be used to access array elements rather than using constructs involving “[ ]”  Pointers in C are automatically scaled by the size of the object pointed to when involved in arithmetic long v[6] = { 1. printf("%ld\n".2. p += 4.

p--. printf("%ld\n". long v[6] = { 1.Pointers Go Backwards Too  Scaling not only happens when addition is done. *p). *p).5.4. p--. p = v + 5. 3. p-=2 p 6 6 5 5 3 3 1020 v 1 2 3 p-4 5 6 1016 1000 1008 1012 1020 1004 . p -= 2. printf("%ld\n".6 }. printf("%ld\n".4. *p). printf("%ld\n". p = v + 5. long *p. long *p. printf("%ld\n".2. 3.5.6 }. *p). printf("%ld\n".2. it happens with subtraction too long v[6] = { 1. p -= 2. *p). *p).

5. p2 . 5.4 5.7 }.4. giving the number of array elements separating them double double d[7] = { 1. printf("%i\n". 4. p1 = d + 1.3 4. printf("%i\n".2 3.Pointers May be Subtracted  When two pointers into the same array are subtracted C scales again.p1). d[7] = { 1. double double *p1.1.2. *p2.5 6.4. 5. 4.2.6. 3.5.p1). 6.1 2. p2 .3. p2 = d + 6. p2 = d + 6.7 2000 2016 2032 2048 2008 2024 2040 .7 }. 7. 6. 2. double double *p2. 3. *p1.6 7.1. 5 5 p1 2008 p2 2048 d 1.6. 7.3. p1 = d + 1. 2.

3. 6)). int sz) { { long *end = p + sz. 2. 6)). } } return total. 7. total += *p++.Using Pointers . return total. 5. primes 1 2 3 5 7 11 1000 1004 1008 1012 1016 1020 1024 p 1000 end 1024 } } long sum(long *p. int sz) long sum(long *p. return 0. int). printf("%li\n". 7. 11 }. return 0. 5. sum(primes. 11 }. long sum(long*. while(p < end) while(p < end) total += *p++.h> #include <stdio. int int { { main(void) main(void) long primes[6] = { 1. printf("%li\n". 2. 3. . long total = 0. int).Example #include <stdio. sum(primes. long *end = p + sz. long primes[6] = { 1.h> long sum(long*. long total = 0.

* and ++ *p++ means: *p++ find the value at the end of the pointer *p++ increment the POINTER to point to the next element (*p)++ means: (*p)++ find the value at the end of the pointer (*p)++ increment the VALUE AT THE END OF THE POINTER (the pointer never moves) *++p means: *++p increment the pointer *++p find the value at the end of the pointer .

50. printf("%i\n". 50. a[3]). 70. p[3]). printf("%i\n". printf("%i\n". short *p = a. printf("%i\n". 3[a]). 30. printf("%i\n". printf("%i\n". a[3]). 40 40 40 40 40 40 40 40 40 40 p 1000 a 10 20 30 40 50 60 70 80 1000 1004 1008 1012 1002 1006 1010 1014 . 70. *(a + 3)). 60. short a[8] = { 10. 40. 20. 60. *(p + 3)). *(a + 3)).Which Notation?  An axiom of C states a[i] is equivalent to *(a + i) short a[8] = { 10. 40. *(p + 3)). 3[a]). 30. 80 }. printf("%i\n". short *p = a. p[3]). printf("%i\n". 20. printf("%i\n". printf("%i\n". 80 }.

instead we use arrays of char  A special character.Strings  C has no native string type. or the compiler may add it for us . marks the end (don’t confuse this with the NULL pointer )  This may be written as ‘\0’ (zero not capital ‘o’)  This is the only character whose ASCII value is zero  Depending on how arrays of characters are built. called a “null”. we may need to add the null by hand.

first_name[5] = { 'J'.Example char char char char char char char char first_name[5] = { 'J'. 'n'. '\0' }. '\0' }. last_name[6] = "Minor". other[] = "Tony Blurt". other[] = "Tony Blurt". 'o'. characters[7] = "No null". 'o'. characters[7] = "No null". this special case specifically excludes the null terminator first_name last_name other characters 'J' 'M' 'T' 'N' 'o' 'i' 'o' 'o' 'h' 'n' 'n' 32 'n' 'o' 'y' 'n' 0 'r' 32 'u' 0 'B' 'l' 'l' 'l' 'u' 'r' 't' 0 . last_name[6] = "Minor". 'n'. 'h'. 'h'.

*p++). char *p. p = other. other[i++]). other). printf("%s\n". . printf("%c". printf("\n"). other). printf("\n"). while(other[i] != '\0') while(other[i] != '\0') printf("%c". while(*p != '\0') while(*p != '\0') printf("%c". other[] = "Tony Blurt".Printing Strings  Strings may be printed by hand  Alternatively printf supports “%s” char char other[] = "Tony Blurt". char *p. other[i++]). printf("%c". printf("%s\n". printf("\n"). *p++). p = other. int i = 0. int i = 0. printf("\n").

h> int int { { main(void) main(void) char char other[] = "Tony Blurt". other[4] = '\0'. other). other). other). other[] = "Tony Blurt".h> #include <stdio. printf("%s\n".Null Really Does Mark the End! #include <stdio. } } return 0. even though the rest of the data is still there. other). printf("%s\n". Tony Blurt Tony Blurt Tony Tony other 'T' 'o' 'n' 'y' 32 'B' 'l' 'u' 'r' 't' 0 . printf("%s\n". printf will NOT move past the null terminator printf("%s\n". other[4] = '\0'. return 0.

char who[] = "Tony Blurt".h> int int { { main(void) main(void) char who[] = "Tony Blurt". return 0.Assigning to Strings  Strings may be initialised with “=”.h> #include <string. who = "John Minor". "John Minor"). return 0. but not assigned to with “=”  Remember the name of an array is a CONSTANT pointer to the zeroth element #include <stdio.h> #include <string. } } . strcpy(who. strcpy(who. who = "John Minor".h> #include <stdio. "John Minor").

*q = "nt!!".Pointing to Strings  To save us declaring many character arrays to store strings. *q = "nt!!". q 0xF10A 0xF10A . the compiler can store them directly in the data segment  We need only declare a pointer  The compiler may recycle some of these strings. therefore we must NOT alter any of the characters char char char char p 0xF100 'D' 0xF100 'a' 't' 'a' 32 's' 'e' 'g' 'm' 'e' 'n' 't' '!' '!' 0 *p = "Data segment!!". *p = "Data segment!!".

} } return 0. printf("a third string in the data segment\n"). "a second string in the data segment\n". printf(p). printf("%s". p). unfortunately we forget to save the address #include <stdio.h> int int { { main(void) main(void) char char *p = "a string in the data segment\n".h> #include <stdio. a third string in the data segment a third string in the data segment a string in the data segment a string in the data segment a string in the data segment a string in the data segment . "a second string in the data segment\n". printf(p). return 0. p). printf("a third string in the data segment\n").Example this utterly pointless statement causes the compiler to store the characters. printf("%s". *p = "a string in the data segment\n".

int day_of_year = 238. C does support arrays of any type including arrays of arrays float rainfall[12][365].0F. short exam_marks[500][10]. rainfall[brighton][day_of_year] = 0.Multidimensional Arrays  C does not support multidimensional arrays  However. int day_of_year = 238. const int brighton = 7. const int brighton = 7. float rainfall[12][365].0F. “rainfall” is an array of 12 arrays of 365 float “exam_marks” is an array of 500 arrays of 10 short int short exam_marks[500][10]. . rainfall[brighton][day_of_year] = 0.

h> #include <stdio. for(i = 0. i. . i <= 10. a[10]. a[10]. printf("%d\n". i++) { printf("%d\n". i). a[i] = 0. } } } } return 0. i <= 10. i).h> int int { { main(void) main(void) int int int int i.Review  How many times does the following program loop? #include <stdio. a[i] = 0. return 0. i++) { for(i = 0.

“[ ]” and an integer  Arrays passed into functions by pointer  Pointer arithmetic  Strings .Summary  Arrays are declared with a type.arrays of characters with a null terminator  Sometimes compiler stores null for us (when double quotes are used) otherwise we have to store it ourselves . “[ ]” and a CONSTANT  Access to elements by array name. a name.

Structures in C        Concepts Creating a structure template Using the template to create an instance Initializing an instance Accessing an instance’s members Passing instances to functions Linked lists .

including arrays or other structures  The steps are: – set-up a template (blueprint) to tell the compiler how to build the structure – Use the template to create as many instances of the structure as desired – Access the members of an instance as desired .Concepts  A structure is a collection of one of more variables grouped together under a single name for convenient handling  The variables in a structure are called members and may have any type.

int day. due. struct Date dob. }. }. char address[200]. struct Library_member struct Library_member { { char name[80]. float price. }. }. }. struct Date enrolled. }. char name[80]. char isbn[20].Setting up the Template  Structure templates are created by using the struct keyword struct Date struct Date { { int day. char author[80]. long member_number. long member_number. struct Date dob. b. due. char isbn[20]. }. *who. struct Book struct Book { { char title[80]. struct Library_book struct Library_book { { struct Book struct Book struct Date struct Date struct Library_member struct Library_member }. . struct Date enrolled. float fines[10]. char address[200]. int month. float price. int year. float fines[10]. *who. int month. int year. char author[80]. char title[80]. b.

} today.’ .. tomorrow. an instance (or instances) of the structure may be declared struct Date struct Date { { int day.. struct Date next_week[7]. instances must be declared before the ‘. struct Date next_monday.. int year. struct Date next_week[7]. int month. tomorrow.Creating Instances  Having created the template. } today. struct Date next_monday. int month. or “struct Date” has to be repeated an array of 7 date instances . . int day. int year..

3. 31. Ritchie". char char char char float float char char }. 7. price. isbn[20]. title[80]. price. int primes[7] = { 1. "Brian W. 13 }. 11. 5. 2.95. isbn[20]. Ritchie". 2. "The C Programming Language 2nd edition". Kernighan and Dennis M. struct Date struct Date bug_day = { 1. "Brian W. 3. 13 }. bug_day = { 1. {{ }. Kernighan and Dennis M. 1.Initialising Instances  Structure instances may be initialised using braces (as with arrays) int primes[7] = { 1. "0-13-110362-8" struct Book "0-13-110362-8" struct Book }. title[80]. }. 31. 5. 1. 2000 }. author[80].95. 7. 11. . struct Book struct Book k_and_r = { k_and_r = { "The C Programming Language 2nd edition". 2000 }. author[80].

float fines[10].10. 42. "16 New Bypass". struct Date dob. { 18. 9.0 struct Library_member m = { struct Library_member m = { "Arthur Dent".Structures Within Structures struct Library_member struct Library_member {{ char name[80]. }. 2.13. long member_number. initialises day. month and year of “enrolled” . { 1. 1. 42. long member_number. }. float fines[10]. 0. 1. "16 New Bypass". char address[200]. 1959 }. 1978 } { 1. month and year of “dob” initialises day.13. initialises first 4 elements of array “fines”. 1959 }. 1978 } }. 0. remainder are initialised to 0. "Arthur Dent". 4. struct Date dob. struct Date enrolled.10 }.10 }. struct Date enrolled. 4. { 18. char name[80].58. }. { 0.10. { 0.58. 2. char address[200]. 9.

name). m.enrolled.member_number). long member_number.fines[i] > 0. printf("membership number = %li\n".month. m.enrolled.fines[i]). float fines[10]. i++) for(i = 0. char name[80]. struct Date enrolled. }. printf("fines: ").enrolled. struct Date dob. printf("membership number = %li\n". i++) printf("£%. m. char address[200]. printf("name = %s\n".0.member_number).2f ". struct Date dob. printf("\njoined %i/%i/%i\n". . m. for(i = 0.month. struct Library_member m.enrolled. printf("fines: ").enrolled. m.day. i < 10 && m. char address[200]. printf("\njoined %i/%i/%i\n".fines[i] > 0. m. m. float fines[10]. m.Accessing Members  Members are accessed using the instance name.year). }. m.name).day. m. m.2f ".year). “. printf("name = %s\n".enrolled. long member_number. i < 10 && m. printf("£%.” and the member name struct Library_member struct Library_member {{ char name[80].0. m. struct Date enrolled. struct Library_member m.fines[i]).

Unusual Properties  Structures have some very “un-C-like” properties. certainly when considering how arrays are handled Arrays Name is Passed to functions by Returned from functions May be assigned with “=” pointer to zeroth element pointer no way no way Structures the structure itself value or pointer by value or pointer yes .

}. Date structure “dob” and Date structure “enrolled” . struct Library_member tmp. long integer “member_number”. struct Library_member tmp.. tmp = m. tmp = m. "Arthur Dent". array “address”.Instances may be Assigned  Two structure instances may be assigned to one another via “=”  All the members of the instance are copied (including arrays or other structures) struct Library_member m = { struct Library_member m = { "Arthur Dent".. copies array “name”. array “fines”.. }. .... ...

by_reference(struct Library_member *). by_value(m). by_value(struct Library_member). by_reference(&m). by_reference(&m). by_reference(struct Library_member *). compiler writes a pointer (4 bytes?) onto the stack compiler writes 300+ bytes onto the stack . by_value(m).Passing Instances to Functions  An instance of a structure may be passed to a function by value or by pointer  Pass by value becomes less and less efficient as the structure size increases  Pass by pointer remains efficient regardless of the structure size void void void void by_value(struct Library_member).

enrolled.month. i++) for(i = 0. printf("membership number = %li\n".enrolled. i < 10 && (*p). printf("name = %s\n".0. printf("\njoined %i/%i/%i\n". (*p). printf("membership number = %li\n".2f ". (*p).year). i++) printf("£%. (*p). (*p).month. (*p).enrolled.day. (*p).2f ".enrolled. for(i = 0.member_number).fines[i] > 0.fines[i]).member_number).fines[i]). (*p).enrolled.fines[i] > 0. (*p).name). printf("fines: ").0. printf("fines: ").Pointers to Structures  Passing pointers to structure instances is more efficient  Dealing with an instance at the end of a pointer is not so straightforward! void void member_display(struct Library_member *p) member_display(struct Library_member *p) { { printf("name = %s\n".day. (*p). } } . (*p). printf("\njoined %i/%i/%i\n".enrolled. printf("£%. (*p).year). (*p).name). i < 10 && (*p).

name .name points to” (a problem because there is no structure instance “p”)  As Kernighan and Ritchie foresaw pointers and structures being used frequently they invented a new operator p->name = (*p).Why (*p).name ?  The messy syntax is needed because “. thus: *p.” has higher precedence than “*”.name means “what p.

year). p->name).Using p->name  Now dealing with the instance at the end of the pointer is more straightforward void void member_display(struct Library_member *p) member_display(struct Library_member *p) { { printf("name = %s\n". i++) for(i = 0. printf("address = %s\n".month. p->address).0. i < 10 && p->fines[i] > 0. for(i = 0. i < 10 && p->fines[i] > 0. p->address).month. printf("\njoined %i/%i/%i\n". printf("\njoined %i/%i/%i\n". printf("£%. i++) printf("£%. p->member_number). p->enrolled. p->name). p->fines[i]). } } . printf("membership number = %li\n". printf("fines: "). p->enrolled. printf("address = %s\n". p->enrolled. printf("fines: ").2f ". p->enrolled. printf("name = %s\n".year). p->member_number).2f ".day.0. printf("membership number = %li\n". p->fines[i]).day. p->enrolled. p->enrolled.

Pass by Reference . p->fines[i]). } } function alters the library member instance void void member_display(const struct Library_member *p) member_display(const struct Library_member *p) { { . for(i = 0. the function can alter the structure (perhaps inadvertently)  Use a pointer to a constant structure instead void void member_display(struct Library_member *p) member_display(struct Library_member *p) { { printf("fines: ").. i++) printf("£%...Warning  Although pass by reference is more efficient.2f ". printf("£%... p->fines[i]). printf("fines: ").. } } . i < 10 && p->fines[i] = 0. i < 10 && p->fines[i] = 0. .0.0. i++) for(i = 0.2f ".

0.imag_part.1 }. c3 = add(c1. 1. result. c2).real_part.imag_part += b.real_part += b. result.Returning Structure Instances  Structure instances may be returned by value from functions  This can be as inefficient as with pass by value  Sometimes it is convenient! struct Complex add(struct Complex a. /* c3 = c1 + c2 */ c3 = add(c1. result. struct Complex c2 = { 2. struct Complex c3.1 }. struct Complex c3.0.imag_part. 1. /* c3 = c1 + c2 */ . 2. struct Complex b) { { struct Complex result = a. struct Complex b) struct Complex add(struct Complex a. result. struct Complex c2 = { 2. c2).0. struct Complex c1 = { 1. struct Complex c1 = { 1. struct Complex result = a.0.1 }.real_part += b. } } return result.imag_part += b. 2.real_part. return result.1 }.

}. data. *previous_in_line.Linked Lists  A linked list node containing a single forward pointer may be declared as follows struct Node { struct Node { int int struct Node struct Node }. data. /* or whatever */ *next_in_line. pointer to next Node structure  A linked list node containing a forward and a backward pointer may be declared as follows struct Node { struct Node { int int struct Node struct Node struct Node struct Node }. *next_in_line. data. }. *next_in_line. /* or whatever */ data. pointer to next Node structure pointer to previous Node structure . *previous_in_line. *next_in_line.

&a3 }. struct Node a2 = { "Harriet".Example #include <stdio. struct Node a2 = { "Harriet". struct Node a3 = { "Claire".h> #include <stdio. name[10]. &a1 }. struct Node a1 = { "John". a4 Tony\0 0x1020 0x1012 a3 Claire\0 0x102E 0x1020 a2 Harriet\0 0x1032 0x102E a1 John\0 NULL 0x1032 . &a2 } struct Node a4 = { "Tony". &a2 } struct Node a3 = { "Claire". NULL }. name[10]. *next_in_line. &a3 }.h> struct Node { struct Node { char char struct Node struct Node }. struct Node a1 = { "John". &a1 }. }. NULL }. *next_in_line. struct Node a4 = { "Tony".

current = current->next_in_line. current->name).Printing the List  The list may be printed with the following code: struct Node * current = &a4. struct Node * current = &a4. printf("%s\n". while(current != NULL) { while(current != NULL) { printf("%s\n". current = current->next_in_line. current->name). } } current 0x1012 a4 Tony\0 0x1020 0x1012 Claire\0 0x102E 0x1020 Harriet\0 0x1032 0x102E John\0 NULL 0x1032 .

Summary Creating structure templates using struct Creating and initialising instances Accessing members Passing instances to functions by value and by reference  A new operator: “->”  Return by value  Linked lists     .

Reading C Declarations      Introduction SOAC Examples typedef Examples revisited .

(*f)(char. (*f)(char. (*pfa)[23]. .  However. p. they can become much worse: int int float float long long double double *p[15]. int). p. void member_display(const struct Library_member *p). *(*(*n)(void))[5].  Plus a few trickier ones: void member_display(const struct Library_member *p). *p[15]. (*pfa)[23]. sum. *(*(*n)(void))[5].Introduction  Up until now we have seen straightforward declarations: long long int* int* sum. int).

SOAC  Find the variable being declared  Spiral Outwards Anti Clockwise  On meeting: say: * [] () pointer to array of function taking . and returning  Remember to read “struct S”.... “union U” or “enum E” all at once  Remember to read adjacent collections of [ ] [ ] all at once .

 What is “int * p[15]” ? int * p [15] .  p is an array of 15 pointers to integers .Example 1.

 p is a pointer to an array of 38 doubles .  What is “double (*p)[38]” ? double (* p ) [38].Example 2.

 ab is an array of 5 arrays of 10 arrays of pointers to pointers to short int .Example 3.  What is “short **ab[5][10]” ? short * * ab [5][10] .

float) .  f is a function taking an int and a float returning a pointer to a long int .  What is “long * f(int. float)” ? long * f (int.Example 4.

 pf is a pointer to a function taking no parameters and returning an int .Example 5.  What is “int (*pf)(void)” ? int ( * pf ) (void) .

 fpa is an array of 8 pointers to functions. taking no parameters. returning Book structures .Example 6.  What is “struct Book (*fpa[8])(void)” ? struct Book ( * fpa[8] ) (void) .

Example 7.  fprp is a pointer to a function taking no parameters returning a pointer to an array of 6 char .  What is “char (*(*fprp)(void))[6]” ? char ( * ( * fprp ) (void) ) [6] .

taking a char.  ptf is a pointer to a function. returning a pointer to a function. taking an integer.  What is “int * (*(*ptf)(int))(char)” ? int * ( * ( * ptf ) (int) ) (char) .Example 8. returning a pointer to an int .

not a variable .typedef  It doesn’t have to be this difficult!  The declaration can be broken into simpler steps by using typedef  To tackle typedef. pretend it isn’t there and read the declaration as for a variable  When finished remember that a type has been declared.

p is an array of 15 pointer to int .Example 1 Revisited  Simplify “int * p[15]” typedef int * pti . pti is a pointer to an int pti p[15].

Example 3 Revisited
 Simplify “short **ab[5][10]”

typedef

short * * pt_pt_s

;

typedef

pt_pt_s

ao5[5];

pt_pt_s is a pointer to a pointer to a short

ao5 is an array of 5 pointers to pointers to short

ao5

ab[10];

ab is an array of 10 arrays of 5 pointers to pointers to short

Example 5 Revisited
 Simplify “int (*pf)(void)”

typedef int

fri(void);

fri

* pf

;

fri is a function, taking no parameters, returning an int

pf is a pointer to a function, taking no parameters, returning an int

Example 6 Revisited
 Simplify “struct Book (*fpa[8])(void)”

typedef struct Book f(void);

typedef f

*

fp

;

f is a function, taking no parameters, returning a Book structure

fp is a pointer to a function, taking no parameters, returning a Book structure

fp

fpa[8];

fpa is an array of 8 pointers to functions, taking no parameters, returning a Book structure

Example 7 Revisited
 Simplify “char (*(*fprp)(void))[6]”

typedef

char

( *

pta6c

) [6] ;

typedef

pta6c f(void);

pta6c is a pointer to an array of 6 char

f is a function, taking no parameters, returning a pointer to an array of 6 char

f

*

fprp

;

fprp is a pointer to a function, taking no parameters, returning a pointer to an array of 6 char

taking int. typedef pti f(char). ptfri is a pointer to a function.Example 8 Revisited  Simplify “int * (*(*ptf)(int))(char)” typedef int * pti . returning a pointer to an int ptf is a pointer to a function. taking a char. returning a pointer to an int . f is a function. returning a pointer to a function. taking a char. ptfri ( * ptf )(int) . returning a pointer to an int pti is a pointer to an int typedef f * ptfri . taking a char.

use typedef(s) .Spiral Outwards Anti Clockwise  To simplify.Summary  Don’t Panic!  SOAC .

perror Copying files Accessing the command line Dealing with binary files . stdout. stderr Opening files When things go wrong .Handling Files in C        Streams stdin.

the routines will always be there and work the same way. regardless of hardware/operating system  Files are presented as a sequence of characters  It is easy to move forwards reading/writing characters.Introduction  File handling is not built into the C language itself  It is provided by The Standard Library (via a set of routines invariably beginning with “f”)  Covered by The Standard. it is less easy (though far from impossible) to go backwards .

stdin.Streams  Before a file can be read or written. stdout and stderr  stdin (standard input) is connected to the keyboard and may be read from  stdout (standard output) and stderr (standard error) are connected to the screen and may be written to . a data structure known as a stream must be associated with it  A stream is usually a pointer to a structure (although it isn’t necessary to know this)  There are three streams opened by every C program.

or written a block at a time to the file a b c d e f g h i j k l output stream a b c d e f g h i j input stream . a stream creates a buffer between the program running in memory and the file on the disk  This reduces the program’s need to access slow hardware devices  Characters are silently read a block at a time into the buffer.What is a Stream?  Although implementations vary.

supported by Unix. "written to stderr\n"). fprintf(stderr. return 0.h> int main(void) int main(void) { { printf("written to stdout\n").Why stdout and stderr?  There are two output streams because of redirection.h> #include <stdio.txt C:> type file. C:> outprog C:> outprog written to stderr written to stderr written to stdout written to stdout C:> outprog > file. fprintf(stderr.txt written to stderr written to stderr C:> type file. printf("written to stdout\n"). "written to stderr\n").txt written to stdout written to stdout output written to stderr first because it is unbuffered .txt C:> outprog > file. } } return 0. DOS. #include <stdio. OS/2 etc.

ch). printf("EOF\n"). even though we are dealing with characters C:> inprog C:> inprog abc abc read 'a' read 'a' read 'b' read 'b' read 'c' read 'c' read ' read ' ' ' d d read 'd' read 'd' read ' read ' ' ' ^Z ^Z EOF EOF C:> C:> } } .stdin is Line Buffered  Characters typed at the keyboard are buffered until Enter/Return is pressed #include <stdio. return 0. printf("EOF\n"). printf("read '%c'\n". int ch.h> #include <stdio. return 0. ch). declared as an int.h> int main(void) int main(void) { { int ch. while((ch = getchar()) != EOF) while((ch = getchar()) != EOF) printf("read '%c'\n".

"r"). "a"). const char* mode). FILE* fopen(const char* name.bat". out = fopen("autoexec. out.h> #include <stdio. in = fopen("autoexec.Opening Files  Files are opened and streams created with the fopen function FILE* fopen(const char* name.sys". const char* mode). "a"). in = fopen("autoexec. in. append = fopen("config. #include <stdio. append.bat".bak". . out. "w"). out = fopen("autoexec. append.sys".h> int main(void) int main(void) { { FILE* FILE* FILE* FILE* FILE* FILE* streams. you’ll need one for each file you want open in. "w"). "r"). append = fopen("config.bak".

fprintf(stderr.bat failed because: No such file or directory . "open of autoexec. #include <stdio. "r")) == NULL) { if((in = fopen("autoexec. "open of autoexec.Dealing with Errors  fopen may fail for one of many reasons. perror("because"). void perror(const char* message).bat". return 1. } } open of autoexec.bat failed ").bat failed ").bat failed because: No such file or directory open of autoexec. if((in = fopen("autoexec. FILE* in. perror("because"). return 1. "r")) == NULL) { fprintf(stderr. how to tell which? void perror(const char* message).bat".h> int main(void) int main(void) { { FILE* in.h> #include <stdio.

despite the file existing and being fully accessible? if((in = fopen("C:\autoexec.bat failed ").183.bat".bat failed because: No such file or directory open of autoexec. return 1.183. "r")) == NULL) { fprintf(stderr.File Access Problem  Can you see why the following will ALWAYS fail.264. perror("because").bat failed ").bat failed because: No such file or directory . return 1.264.bat Volume in drive C is MS-DOS_62 Volume in drive C is MS-DOS_62 Directory of C:\ Directory of C:\ autoexec bat autoexec bat 1 file(s) 1 file(s) 805 29/07/90 8:15 805 29/07/90 8:15 805 bytes 805 bytes 1. "open of autoexec. "open of autoexec.bat C:> dir C:\autoexec. } } C:> dir C:\autoexec.808 bytes free 1.bat". fprintf(stderr.808 bytes free C:> myprog C:> myprog open of autoexec. perror("because"). "r")) == NULL) { if((in = fopen("C:\autoexec.

return 1. in_name). return 0. }} . }} while((ch == fgetc(in_stream)) != EOF) while((ch fgetc(in_stream)) != EOF) putchar(ch). in_name). scanf("%79s". return 0. int ch. printf("Display file: "). int ch. printf("Display file: "). scanf("%79s". fclose(in_stream).h> #include <stdio.Displaying a File #include <stdio. "r")) == NULL) fprintf(stderr. perror("because"). fclose(in_stream). putchar(ch). in_name). return 1. FILE *in_stream. if((in_stream == fopen(in_name. "r")) == NULL) {{ if((in_stream fopen(in_name.h> int main(void) int main(void) {{ char in_name[80]. "open of %s for reading failed ". FILE *in_stream. char in_name[80]. perror("because"). "open of %s for reading failed ". in_name). fprintf(stderr.

in_name). perror("because"). "open of %s for writing failed ". "open of %s for writing failed ". "open of %s for reading failed ". in_name).h> int main(void) int main(void) {{ char in_name[80]. "r")) == NULL) {{ if((in_stream fopen(in_name. *out_stream. scanf("%79s". return 1. if((in_stream == fopen(in_name. perror("because"). return 1. scanf("%79s". out_name). fclose(in_stream).h> #include <stdio. if((out_stream == fopen(out_name. out_name[80]. return 1. int int ch. scanf("%79s". fclose(in_stream). FILE *in_stream. "w")) == NULL) fprintf(stderr. fclose(out_stream). printf("Source file: "). in_name). }} return 0. fputc(ch. fprintf(stderr. FILE *in_stream. char in_name[80]. fclose(out_stream). out_name). out_stream). scanf("%79s". "open of %s for reading failed ". out_name[80].Example . in_name). out_stream). }} while((ch == fgetc(in_stream)) != EOF) while((ch fgetc(in_stream)) != EOF) fputc(ch. perror("because"). ch. return 1. }} printf("Destination file: "). . out_name).Copying Files #include <stdio. printf("Source file: "). perror("because"). "r")) == NULL) fprintf(stderr. "w")) == NULL) {{ if((out_stream fopen(out_name. return 0. fprintf(stderr. out_name). printf("Destination file: "). *out_stream.

000 C:> copyprog \autoexec.* Volume in drive C is MS-DOS_62 Volume in drive C is MS-DOS_62 Directory of C:\ Directory of C:\ autoexec bak autoexec bak autoexec bat autoexec bat 2 file(s) 2 file(s) 805 31/12/99 805 31/12/99 12:34 12:34 805 29/07/90 8:15 805 29/07/90 8:15 1610 bytes 1610 bytes 1.bak Destination file: \autoexec.003 bytes free C:> copyprog \autoexec.Convenience Problem  Although our copy file program works.bat Destination file: \autoexec.264.bat \autoexec.* C:> dir C:\autoexec.bak C:> dir C:\autoexec.000 Source file: Source file: program still prompts despite begin given file names on the command line .183.bat Source file: \autoexec.183. it is not as convenient as the “real thing” C:> copyprog C:> copyprog Source file: \autoexec.264.003 bytes free 1.bat \autoexec.

char *argv[]) argc 3 argv c o p y p r o g . char *argv[]) int main(int argc. b a t \0 \ a u t o e x e c . by convention these are called “argc” and “argv”  The first is a count of the number of words including the program name itself  The second is an array of pointers to the words int main(int argc. 0 0 0 \0 NULL .Accessing the Command Line  The command line may be accessed via two parameters to main. e x e \0 \ a u t o e x e c .

for(j = 0. argv[j]).h> int main(int argc. j.exe" argv[0] = "C:\cct\course\cprog\files\slideprog\argprog. j < argc.h> #include <stdio. char *argv[]) int main(int argc. j.exe" argv[1] = "one" argv[1] = "one" argv[2] = "two" argv[2] = "two" argv[3] = "three" argv[3] = "three" return 0. argv[j]).Example #include <stdio. j++) printf("argv[%i] = \"%s\"\n". return 0. . j < argc. j++) for(j = 0. char *argv[]) { { int j. int j. } } C:> argprog one two three C:> argprog one two three argv[0] = "C:\cct\course\cprog\files\slideprog\argprog. printf("argv[%i] = \"%s\"\n".

FILE* stream).. fputs(const char* buffer.).. FILE* stream).. int fscanf(FILE* stream.  File writing routines: int int int int int int fprintf(FILE* stream. FILE* stream).. FILE* stream). const char* format. const char* format. int size.Useful Routines  File reading routines: int fscanf(FILE* stream.). int fgetc(FILE* stream). fputc(int ch.).. int fgetc(FILE* stream). . .). char* fgets(char* buffer.. ... int size. . FILE* stream). FILE* stream). const char* format. char* fgets(char* buffer. fprintf(FILE* stream. fputc(int ch. . fputs(const char* buffer. const char* format.

325|9000000:68000/13 28. l1. fgetc(in). fgets(buf. &d. whichever is less . j. in). &j). f. buf[200]. or next 199 characters. "r") . "%lf|%li:%li/%i". fputs(buf...Example long long int int double double float float char char l1.2lf\n". j. ch... out). &l2. write that line to the output file (null terminator provided by fgets tells fputs how long the line was) 9000000:13:28. l1..txt". fscanf(in. sizeof(buf). fputs(buf. d.325|9000000:68000/13 in = fopen("in.. "%lf|%li:%li/%i".. &l1. l2.... j.33 ignore next character in input file (newline?) read next line. d. "r") . out = fopen("out. fscanf(in.txt". "w") . &j). j. d). f. "%li:%i:%. example input 28. fgetc(in).2lf\n".txt". sizeof(buf). in). out = fopen("out. fgets(buf. d). &l1. l2. ch. "w") . "%li:%i:%.. &l2.. fprintf(out.33 9000000:13:28.txt". in = fopen("in. l1. out). fprintf(out. &d. buf[200].

const fpos_t* pos). FILE* stream). int whence). size_t size. fgetpos(FILE* stream. . size_t n. size_t fwrite(const void* p. fpos_t* pos). size_t n. size_t size. void rewind(FILE* stream). int fseek(FILE* stream. size_t size. long offset. fpos_t* pos). size_t n. FILE* stream). FILE* stream). size_t fwrite(const void* p. long offset. int int int int fgetpos(FILE* stream. long ftell(FILE* stream). long ftell(FILE* stream). FILE* stream). fsetpos(FILE* stream. const fpos_t* pos). fsetpos(FILE* stream. int whence). size_t n.Binary Files  The Standard Library also allows binary files to be manipulated – – – – – “b” must be added into the fopen options Character translation is disabled Random access becomes easier Finding the end of file can become more difficult Data is read and written in blocks size_t fread(void* p. int fseek(FILE* stream. size_t fread(void* p. void rewind(FILE* stream). size_t size.

in). fread(lda. sizeof(long double). sizeof(d). 1. in = fopen("binary. in). 35. move to end of binary. in). fread(lda. sizeof(long double). fseek(in. 35. 20. &where). "wb"). out = fopen("binnew. in). fread(&d. fgetpos(in. 0L. lda[35].dat remember current position in file read one chunk of 350 bytes return to previous position read 35 chunks of 10 bytes write 20 long doubles from lda . "rb"). lda[35]. d. in). 1. sizeof(long double). fgetpos(in. SEEK_END). in).dat". fseek(in. 0L. 20. read one chunk of 8 bytes in = fopen("binary. fread(&d. fsetpos(in. fread(lda.dat".dat". fsetpos(in. fwrite(lda. "rb"). sizeof(long double). sizeof(d). sizeof(lda). fread(lda. "wb"). out).dat". 1. sizeof(lda). 1. &where). where. &where).Example double double long double long double fpos_t fpos_t d. SEEK_END). where. &where). out = fopen("binnew. out). fwrite(lda.

fwrite. fscanf. ftell . stdout. argv  “b” option to fopen to open binary files  functions: fread.Summary  Streams stdin. fprintf. fseek. fgetc. fputc  variables: argc. stderr  fopen opening text files  functions: perror.

Miscellaneous Things     Unions Enumerated types The Preprocessor Working with multiple .c files .

s.d == 10. s. l.01. u s. u. d. s.s == 10.c == '1'. u. c. d. s. may hold objects of different types and sizes s struct SS struct {{ short short long long double double char char }} s.d 10. u.Unions  A union is a variable which. s.c '1'. u. c.d == 10. d. c. s. s. .s 10.l 10L. l. s.c == '1'. u.l == 10L. c.01. u.l 10L. s. s. l. s. u. union UU union {{ short short long long double double char char }} u. u.c '1'.d 10.01.01. d. l. at different times. u.s 10.l == 10L. s.s == 10.

double dval. s[0].name "N_SIZE".stored == STORED_LONG. double dval.Remembering  It is up to the programmer to remember what type a union currently holds  Unions are most often used in structures where a member records the type currently stored struct preprocessor_const struct preprocessor_const {{ char* name. char* name.1416 3. }. s[0]. s[0].u. char* sval. struct preprocessor_const s[10000]. long lval.lval == 10L.u. . union union {{ long lval. s[0]. s[0]. s[1]. s[1]. int stored. }} u.name == "N_SIZE". s[1].stored STORED_DOUBLE. s[1]. s[0].stored == STORED_DOUBLE.dval 3.1416. int stored. s[1].u.dval == 3.name "PI".lval 10L.1416.name == "PI".1416 struct preprocessor_const s[10000]. s[1]. u. #define N_SIZE #define N_SIZE #define PI #define PI 10 10 3.u. char* sval.stored STORED_LONG. }.

Enumerated Types  Enumerated types provide an automated mechanism for generating named constants #define sun #define sun #define mon #define mon #define tue #define tue #define wed #define wed #define thu #define thu #define fri #define fri #define sat #define sat 0 0 1 1 2 2 3 3 4 4 5 5 6 6 enum day { sun. wed... if(today == mon) if(today == mon) . enum day today = sun.. . tue.. enum day { sun. int today = sun... thu.... if(today == mon) if(today == mon) . int today = sun. fri. thu. .. enum day today = sun.. wed. fri. mon. tue. . sat }.. mon. sat }.

Using Different Constants  The constants used may be specified enum day { sun = 5. wed. east = 90. east = 90. thu. wed. tue. sat }. enum direction { north = 0. fri.  What you see is all you get!  There are no successor or predecessor functions . south = 180. tue. mon. south = 180. fri. mon. west = 270 }. west = 270 }. thu. enum day { sun = 5. sat }. enum direction { north = 0.

test and compare constants write macros debug .The Preprocessor  Preprocessor commands start with ‘#’ which may optionally be surrounded by spaces and tabs  The preprocessor allows us to: – – – – include files define.

double my_global. printf("%s". printf("%s". month[2]). myprog.i myprog. month[2]).1416 #define JAN #define JAN #define FEB #define FEB #define MAR #define MAR #define PI #define PI double my_global.h" double angle == 22 ** PI. printf("%s". double angle PI. double angle 3. 11 22 33 3.1416 mydefs.1416 3.Including Files  The #include directive causes the preprocessor to “edit in” the entire contents of another file #define JAN #define JAN #define FEB #define FEB #define MAR #define MAR #define PI #define PI double my_global. month[FEB]). month[FEB]). double my_global.1416. double angle == 22 ** 3. printf("%s".c .h" #include "mydefs.h #include "mydefs.1416. 11 22 33 3.1416 3.

h" cc -I c:\cct\course\cprog\misc\slideprog myprog.c cc -I c:\cct\course\cprog\misc\slideprog myprog.Pathnames  Full pathnames may be used.h" #include "header.c . although this is not recommended #include "C:\cct\course\cprog\misc\slideprog\header.h"  The “I” directive to your local compiler allows code to be moved around much more easily #include "header.h" #include "C:\cct\course\cprog\misc\slideprog\header.

then begin remove definition of “SUN” end if “TUE” is defined with a non zero value if “WED” is greater than zero or “SUN” is less than 3 if “SUN” is greater than “SAT” and “SUN” is greater than “MON” . tested and removed #if !defined(SUN) #if !defined(SUN) #define #define SUN SUN 0 0 #endif #endif #if SUN == MON #if SUN == MON #undef SUN #undef SUN #endif #endif #if TUE #if TUE #if WED > 0 || SUN < 3 #if WED > 0 || SUN < 3 #if SUN > SAT && SUN > MON #if SUN > SAT && SUN > MON if “SUN” is not defined. then begin define “SUN” as zero end if “SUN” and “MON” are equal.Preprocessor Constants  Constants may be created.

Avoid Temptation!  The following attempt to write Pascal at the C compiler will ultimately lead to tears #define #define #define #define #define #define #define #define #define #define integer integer begin begin end end if if then then integer integer i. i.} .} if i > 0 then begin if i > 0 then begin i = 17 i = 17 end end . if( i > 0 ) { if( i > 0 ) { i = 17 i = 17 .} if( if( ) ) int int int i.} . { { . int i.

Y) A > B ? A : B A > B ? A : B ((X) < (Y) ? (X) : (Y)) ((X) < (Y) ? (X) : (Y)) int i = 10. k). printf("k = %i\n". j++). k). k. k = 12 printf("i = %i\n". k. printf("k = %i\n".B) MIN(X. k). i) * 2. k = 12 printf("i = %i\n". j). k).Preprocessor Macros  The preprocessor supports a macro facility which should be used with care #define #define #define #define MAX(A. i).Y) MIN(X. i) * 2. printf("k = %i\n". printf("k = %i\n". int i = 10. j) * 3. k = MIN(i. k = 12 k = 12 k = 30 k = 30 i = 8 i = 8 . k = MAX(i. printf("k = %i\n".B) MAX(A. i). k = MAX(i. j = 12. k = MAX(j. k = MAX(j. j) * 3. j++). j = 12. j). k). printf("k = %i\n". k). k = MIN(i--. k = MIN(i--. k = MIN(i.

_ _FILE_ _) _ _LINE_ _. printf("i = %x\n". f/29.5 = %lf\n". i). "%lf"). . "mysource. "%x").c"). i). \ printf("reached %i in %s\n". 17.5). printf("f/29. FMT) SHOW(E. "%x"). GOT_HERE. f/29. SHOW(i. SHOW(f/29.A Debugging Aid  Several extra features make the preprocessor an indespensible debugging tool #define #define #define #define GOT_HERE GOT_HERE SHOW(E. FMT) printf("reached %i in %s\n". printf("f/29.5 = %lf\n". SHOW(f/29. E) printf("reached %i in %s\n". SHOW(i. GOT_HERE. "mysource. _ _FILE_ _) printf(#E " = " FMT "\n".5. E) printf(#E " = " FMT "\n". \ _ _LINE_ _.c"). "%lf").5. 17. printf("reached %i in %s\n". printf("i = %x\n".5).

Working With Large Projects  Large projects may potentially involve many hundreds of source files (modules)  Global variables and functions in one module may be accessed in other modules  Global variables and functions may be specifically hidden inside a module  Maintaining consistency between files can be a problem .

start < stop. 5. for(.8 + 32). start. printf("%. print_table(0.start < stop.5F). step = 0. float).h> return 0. float stop) void print_table(double start.h> return 0. start += step) printf("%. #include <stdio. printf("Celsius\tFarenheit\n"). start * 1.8 + 32). } float step. start.Data Sharing Example extern float step. float). void print_table(double start. extern float step. print_table(0. void print_table(double.1lf\t%.0. } } .1lf\n". int main(void) int main(void) { { step = 0.5F).1lf\n". 5. start += step) for(.15F.0. #include <stdio.1lf\t%. start * 1. float stop) { { printf("Celsius\tFarenheit\n"). void print_table(double.15F. } float step.

int pop(void). { extern int entries[]. void push(int value) void print(void). static int current. void push(int value) void print(void). push(15). { extern int entries[]. return entries[--current].Data Hiding Example  When static is placed before a global variable. int pop(void) push(10). static void print(void) print(). static void print(void) { { return 0. { printf("%i\n". int pop(void). static int current. push(15). static int entries[S_SIZE]. the item is locked into the module static int entries[S_SIZE]. } print(). pop()). or function. return entries[--current]. void push(int value). entries[3] = 77. } } } } . void push(int value). pop()). { printf("%i\n". return 0. entries[current++] = value entries[current++] = value int main(void) } int main(void) } { { int pop(void) push(10). } entries[3] = 77.

start += step) for(. 5.h> return 0. printf("Celsius\tFarenheit\n").1lf\n". start * 1.5F). print_table(0. } double step. } } .0. void print_table(double start.15F. printf("%. #include <stdio. int main(void) int main(void) { { step = 0.15F.start < stop.start < stop.8 + 32). start * 1.Disaster! extern float step. void print_table(double. 5.0. start. } double step.5F). void print_table(double.h> return 0. start += step) printf("%.1lf\t%. double stop) { { printf("Celsius\tFarenheit\n").1lf\t%. #include <stdio. float). double stop) void print_table(double start. print_table(0.1lf\n". float). step = 0. for(. start.8 + 32). extern float step.

sharable) function in a module .e.Use Header Files  Maintain consistency between modules by using header files  NEVER place an extern declaration in a module  NEVER place a prototype of a non static (i.

Getting it Right
project.h extern double step; extern double step; void print_table(double, double); void print_table(double, double);

#include "project.h" #include "project.h" int main(void) int main(void) {{ step == 0.15F; step 0.15F; print_table(0.0, 5.5F); print_table(0.0, 5.5F); }} return 0; return 0;

#include <stdio.h> #include <stdio.h> #include "project.h" #include "project.h" double step; double step; void print_table(double start, double stop) void print_table(double start, double stop) {{ }}

Be as Lazy as Possible
 Get the preprocessor to declare the variables too!
#if defined(MAIN) #if defined(MAIN) #define #define EXTERN EXTERN #else #else #define #define EXTERN EXTERN #endif #endif EXTERN double EXTERN double EXTERN long EXTERN long EXTERN short EXTERN short

extern extern

step; step; current; current; res; res;

#define MAIN #define MAIN #include "globals.h" #include "globals.h" main.c

#include "globals.h" #include "globals.h" first.c

#include "globals.h" #include "globals.h" second.c

Summary
 A union may store values of different types at different times  enum provides an automated way of setting up constants  The preprocessor allows constants and macros to be created  Data and functions may be shared between modules  static stops sharing of data and functions  Use the preprocessor in large, multi module projects

C and the Heap
     What is the Heap? Dynamic arrays The calloc/malloc/realloc and free routines Dynamic arrays of arrays Dynamic data structures

What is the Heap?
 An executing program is divided into four parts:  Stack: provides storage for local variables, alters size as the program executes  Data segment: global variables and strings stored here. Fixed size.  Code segment: functions main, printf, scanf etc. stored here. Read only. Fixed size  Heap: otherwise known as “dynamic memory” the heap is available for us to use and may alter size as the program executes

How Much Memory?
 With simple operating systems like MS-DOS there may only be around 64k available (depending on memory model and extended memory device drivers)  With complex operating systems using virtual memory like Unix, NT, OS/2, etc. it can be much larger, e.g. 2GB  In the future (or now with NT on the DEC Alpha) this will be a very large amount (17 thousand million GB)

their size is fixed at run time and may be changed as often as required  Only a pointer is required .their size must be fixed when the program is written  There is no way to increase (or decrease) the size of an array once the program is compiled  Dynamic arrays are different.Dynamic Arrays  Arrays in C have a fundamental problem .

Using Dynamic Arrays  The following steps create a dynamic array:  Declare a pointer corresponding to the desired type of the array elements  Initialise the pointer via calloc or malloc using the total storage required for all the elements of the array  Check the pointer against NULL  Increase or decrease the number of elements by calling the realloc function  Release the storage by calling free .

printf("How many doubles? "). i++) here we access the “s” for(i = 0. return 0. s * sizeof(double). s. &s). i++) p[i] = i.h> #include <stdio. i < s. doubles from 0. "Cannot allocate %u bytes " fprintf(stderr. scanf("%u". all of the allocated memory is freed return 0.h> #include <stdlib.s-1 p[i] = i. sizeof(double))) == NULL) { if((p = calloc(s. s * sizeof(double). free(p). if((p = calloc(s.h> int main(void) int main(void) { { unsigned unsigned i. i. sizeof(double))) == NULL) { fprintf(stderr. } } for(i = 0. s). free(p).calloc/malloc Example #include <stdio. return 1. "for %u doubles\n". "Cannot allocate %u bytes " "for %u doubles\n". &s). return 1. i < s. if((p = malloc(s * sizeof(double))) == NULL) { if((p = malloc(s * sizeof(double))) == NULL) { } } . scanf("%u". s). s. double *p. printf("How many doubles? "). double *p.h> #include <stdlib..

*p2. how many now? ". at this point } } p = p2. "for %u doubles\n". free(p). free(p). *p. free(p). return 1. "to contain %u doubles\n". if((p = calloc(s. scanf("%u". s). "Cannot allocate %u bytes " "for %u doubles\n". printf("%u doubles currently. free(p). "Could not increase/decrease array " "to contain %u doubles\n". how many now? ". p = p2. s). pointer “p” is invalid at this point. } } printf("%u doubles currently. *p2. return 1. sizeof(double))) == NULL) { fprintf(stderr. s * sizeof(double). sizeof(double))) == NULL) { if((p = calloc(s. s). "Could not increase/decrease array " fprintf(stderr. &s). "Cannot allocate %u bytes " fprintf(stderr. so a new value is assigned to it . p2 = realloc(p. calculate new array p2 = realloc(p. s * sizeof(double)). s). scanf("%u". s * sizeof(double)). return 1. s).realloc Example double double double double *p. s). &s). pointer “p” is still valid return 1. size and allocate storage if(p2 == NULL) { if(p2 == NULL) { fprintf(stderr. s * sizeof(double).

. 0). 0).realloc can do it all  The routines malloc and free are almost redundant since realloc can do it all  There is some merit in calloc since the memory it allocates is cleared to zero p = malloc(s * sizeof(double)). s * sizeof(double)). s * sizeof(double)). p = malloc(s * sizeof(double)). p = realloc(NULL. realloc(p. free(p). free(p). realloc(p. p = realloc(NULL.

3F. 365 * sizeof(float)). float (*rainfall)[365]. 365 * sizeof(float)). rainfall[s-1][18] = 4. rainfall[s-1][18] = 4. rainfall = calloc(s. float *p. rain = calloc(s. float (*rainfall)[365]. sizeof(float)).3F. float **rain. rainfall = calloc(s. p = calloc(s. sizeof(float)).Allocating Arrays of Arrays  Care must be taken over the type of the pointer used when dealing with arrays of arrays float *p. 365 * sizeof(float)). . p = calloc(s. float **rain. rain = calloc(s. 365 * sizeof(float)).

data. }. fprintf(stderr. return p. } } return p. p->data = value. struct Node* new_node(int value) struct Node* new_node(int value) { { struct Node* p. . "ran out of dynamic memory\n").Dynamic Data Structures  It is possible to allocate structures in dynamic memory too struct Node { struct Node { int int struct Node struct Node }. if((p = malloc(sizeof(struct Node))) == NULL) { if((p = malloc(sizeof(struct Node))) == NULL) { fprintf(stderr. p->next_in_line = NULL. } } p->data = value. "ran out of dynamic memory\n"). data. exit(9). *next_in_line. *next_in_line. p->next_in_line = NULL. struct Node* p. exit(9).

current = first_node. first_node = new_node(-100). current = first_node. current->data). second_node->next_in_line = third_node.Linking the List struct Node *first_node. current = current->next_in_line. *third_node. *current. current = current->next_in_line. second_node->next_in_line = third_node. second_node = new_node(0). struct Node *first_node. *second_node. *second_node. *third_node. third_node = new_node(10). first_node = new_node(-100). first_node->next_in_line = second_node. printf("%i\n". first_node->next_in_line = second_node. current->data). third_node = new_node(10). while(current != NULL) { while(current != NULL) { printf("%i\n". second_node = new_node(0). *current. } } .

realloc and free manipulate heap storage  Only realloc is really necessary  Allocating dynamic arrays  Allocating dynamic arrays of arrays  Allocating dynamic structures .Summary  The heap and stack grow towards one another  Potentially a large amount of heap storage is available given the right operating system  The routines malloc. calloc.

scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->