1 further c multiple source code file projects structs the preprocessor pointers

26
1 Further C Further C Multiple source code file projects Structs The preprocessor Pointers

Upload: iris-daniel

Post on 28-Dec-2015

223 views

Category:

Documents


0 download

TRANSCRIPT

1

Further CFurther C

Multiple source code file projects Structs The preprocessor Pointers

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;

26

pointers to structures pointers to structures exerciseexercise

Re-use the employee struct

Create a memory block of 100 employee structs

Give them suitable random values

Display them