1 further c multiple source code file projects structs the preprocessor pointers
TRANSCRIPT
2
Multiple source code filesMultiple source code files Real programs are normally written in the form of
several source code files - several .c files Just one file will contain main() In an IDE, the files are listed in a ‘project’ so eg your project might contain files called base.c,
graphics.c, data.c, with main() being in base.c The options are normally -
Compile just one file Build - compiles any changed files, then links Build all - compiles and links all
In a command line environment, you use a ‘make’ utility to do the equivalent
3
Scope across multiple source Scope across multiple source filesfiles
An external variable has scope across all files It can only be defined in 1 file eg
int x; In other files where it needs to be accessed, it
must be declared as extern egextern int x;
Same applies to functions An external defined as static has scope
restricted to the one file egstatic int x;
4
Scope across files - exampleScope across files - example
extern int x in file2.c stops the compiler complaining that x is an undeclared identifier - it is declared in file1.c
#include <stdio.h>
void foo( void);int x;int y;
int main() { foo(); return 0; }
file1.c
extern int x;extern int y;
void foo() { x++; y++; return; }
file2.c
5
Multiple file project exercise Multiple file project exercise
Start a new project
Add two new files to it - called prog1.c and prog2.c
prog1 should contain a global int called x, and a main function
prog2 should contain a function called setX, which makes x equal to 4
The main in prog1 should call setX, then display the value of x
6
A data structure is a way of arranging and organising sets of data items
In C the struct keyword is used to help set up such structures
A struct is like a record or a row in a database - it consists of a set of named fields
The syntax for declaring a struct is likestruct structurename
{type fieldname1;type fieldname2;..}
A variable of this structure is then declared likestruct structurename variablename;
StructuresStructures
7
struct stockItemStruct{
int barCode;double price;int stockLevel;
};
int main() { struct stockItemStruct beans; struct stockItemStruct cornflakes;
beans.barCode = 100; beans.price = 1.49; beans.stockLevel = 50;
cornflakes.barCode = 101; cornflakes.price=2.49; cornflakes.stockLevel = 35;
printf("%i \n", beans.barCode); return 0; }
type
variables
structure member reference
struct examplestruct example
8
struct exercisestruct exercise
Design and write a struct suitable for an employee (no strings so no names yet)
Declare 3 employee variables
Give the fields suitable values
Display the 3 employees
Keep this program for future use
9
The preprocessorThe preprocessor
This is a software tool which acts on the source code carrying out various textual processes - before the compiler operates
Preprocessor directives start with a # The main ones are
#include - for including header files #define - to define constants and macros #if - conditional
10
#include#include
the purpose is to include header files. These define constants and prototype standard library functions
#include “myheader.h” will make the preprocessor look for myheader.h in the current directory - used for headers you write
#include <standard.h> means the preprocessor will look in an implementation-defined directory - used for standard headers like <stdio.h>
11
#define#define used to define constants eg
#define PI 3.1415962no equals, no ;
used to define macros - similar to functions eg macro to find the larger of 2 values:#include <stdio.h>#define bigger( a, b ) a > b ? a : bint main()
{int x;int y = 2, z = 3;x= bigger( y-3, z-1);printf(" x = %i\n",x);
return 0;}
12
macro errorsmacro errors macros are prone to bugs which are hard to see eg a macro to square a number :
#include <stdio.h>#define square( a ) a * aint main()
{int y, x = 2;
y=square( x );printf(" y = %i\n",y); // get 4 - correcty=square( x+1 );printf(" y = %i\n",y); // get 5 - wrong should be 9return 0;}
because square(x) becomes x * x but square ( x +1 ) becomes x + 1 * x + 1
which is 2x+1 not x2
should be square ( a ) ( a ) * ( a )
13
macro exercisemacro exercise
Following the example
#define bigger( a, b ) a > b ? a : b
write a macro called cube which works out the cube of its argument
test it works
14
#if - first technique#if - first technique Writing code which is easily switched between platforms eg a code fragment..
#if defined UNIX...blah - UNIX-specific code...#elif defined MSDOS..DOS-specific code#else#error platform not specified#endif
then put a line in code at start#define UNIXand compile UNIX version, then change that to#define MSDOSand compile an MSDOS version
15
#if - second technique#if - second technique problem with multiple includes eg each source code file in project contains
#include <stdio.h>so the compiler will see lines like#define SEEK_END 2more than once, giving a macro re-definition warning
can solve problem with only doing #include <stdio.h> in one file - but very difficult to track..
solution is like this .. stdio.h starts#ifndef _INC_STDIO#define _INC_STDIO..... rest of it#endif
on the first include, _INC_STDIO is not defined, so it defines it, and all the rest on second and subsequent includes, it is defined, so rest of file ignored
16
pointerspointers
pointers are actually addresses where values are stored in memory
but they are better thought of as being things which ‘point to’ data stored
symbol & means ‘the address of’so &x is the address of x - where it is stored
symbol * means ‘the value stored at’so *p is the value stored at where p points to
17
x=3 does the following.. x is stored at address 1003 (maybe), so.. address value there
1003 3 pointer_variable = &x does this.. &x is the address of x, so pointer_variable
becomes 1003 or, now pointer_variable ‘points to’ x *pointer_variable means the value stored
at the address pointer_variable *pointer_variable = 4; makes the value
stored at pointer_variable to be 4 but that is where x is stored so it changes x to 4 ..
Address value1003 4
pointers - first examplepointers - first example#include <stdio.h>
int main() { int x; int * pointer_variable; x = 3; pointer_variable = &x; *pointer_variable = 4; printf("x = %i\n",x); return 0;}
18
dynamic memory allocationdynamic memory allocation pointers are often used for dynamic storage - the
program requests, uses and releases memory as it runs functions for this are in <malloc.h> int * block; declares block to be a pointer to integer calloc(20, sizeof(int)) requests the use of some
memory - enough for 20 items, each the size of an integer. calloc returns a pointer to the start of it, or NULL if there is not enough memory available
block = calloc(20, sizeof(int)); makes this request, and sets block to point to the start of it
*block is the first integer in this part of memory *(block+1) is the second *(block+19) is the last *(block+20) is the usual error free(block) releases the memory - so the system can
re-use it
19
dynamic memory exampledynamic memory exampleA program to -•get memory to store 20 integers in•store 0, 2, 4, 6, 8.. in it•print them out•release the memory
#include <stdio.h>#include <malloc.h>
int main(){int i;int * block;block = calloc(20, sizeof(int));if (block){for (i=0; i<20; i++)
*(block+i)=2*i;for (i=0; i<20; i++)
printf("Offset %2i Value %i\n",i,*(block+i) );free(block);}return 0;}
Output..Offset 0 Value 0Offset 1 Value 2Offset 2 Value 4Offset 3 Value 6Offset 4 Value 8Offset 5 Value 10Offset 6 Value 12Offset 7 Value 14Offset 8 Value 16Offset 9 Value 18Offset 10 Value 20Offset 11 Value 22Offset 12 Value 24Offset 13 Value 26Offset 14 Value 28Offset 15 Value 30Offset 16 Value 32Offset 17 Value 34Offset 18 Value 36Offset 19 Value 38
20
Pointer exercisePointer exercise
Write a program which -
obtains a block of memory to hold 10 integers
fills the block with random values
prints then out
adds them up and displays the total
21
pointers and arrayspointers and arrays arrays are implemented in C
so that an array with an index is the same as a pointer to the start of a memory block with an offset
the program shown fills an array with 10 random numbers, then outputs them
numbers is declared as an array
When the array is filled, *( numbers + i ) treats numbers as a memory block pointer
When it is output, numbers[ i ]
treats numbers as an array again
#include <stdio.h>#include <stdlib.h>
int main() { int numbers[ 10 ]; int i; for ( i = 0; i < 10; i++ ) *( numbers + i ) = rand(); for ( i = 0; i < 10; i++) printf("%i\n", numbers[ i ] ); return 0; }
22
functions with pointer functions with pointer argumentsarguments arguments are passed to
functions by value ie copies
so foo(x,y) cannot change the values of x and y
functions can accept pointers as arguments
like foo( &x, &y ) this cannot change the
addresses of x and y but it can alter the values
stored at those addresses which are the values of x
and y such as this example
#include <stdio.h>
void swap(int * a, int * b) { // exchange values at a and b int temp; // classic 3-cornered swap.. temp = *a; *a = *b; *b = temp; return; }
int main() { int x=1, y=2; swap(&x, &y); printf("x = %i, y = %i\n", x, y); return 0; }
23
#include <stdio.h>#include <limits.h>#include <stdlib.h>
int * biggest(int * numbers){ int * where; int offset; int biggestsofar = INT_MIN; for (offset=0; offset<10;offset++) if ( *(numbers+offset) > biggestsofar ) { biggestsofar = *(numbers+offset); where = numbers+offset; }
return where;}
•the example coming up uses a function which returns a pointer to the largest value in an array•the main() uses this to find where the biggest number in an array is, then•print that value,•store INT_MIN there•and do this for however many numbers there are there
functions returning pointersfunctions returning pointers
int main() { int data[10]; int i; int * place; for (i=0; i<10; i++) data[i]=rand(); for (i=0; i<10; i++) { place = biggest(data); printf("%i \n", *place); *place = INT_MIN; } return 0; }
Output..2935826962265002446419169184671572411478633441
24
function and pointer exercisefunction and pointer exerciseWrite a program with no global variables but with functions which -
create a block of 10 integers filled with random values
a function to display the values in a memory block
a function to reverse the values in a memory block
main() should call the 'create' block, then display, then reverse, then display again
25
pointers to structspointers to structssuppose we have a struct likestruct productStruct{int barCode;int stockLevel;}
we can create one of these and get a pointer to it bystruct productStruct * prodPtr;prodPtr = calloc(1, sizeof(struct productStruct);
we can access a field in this struct by –(*prodPtr).barCode = 99;
but more convenient is the arrow notation –
prodPtr -> barCode = 99;