1 / 26

Further C

Further C. Multiple source code file projects Structs The preprocessor Pointers. Multiple 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 ’

Download Presentation

Further C

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


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

  2. Multiple 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 files • An external variable has scope across all files • It can only be defined in 1 file egint 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 - example #include <stdio.h> void foo( void); int x; int y; int main() { foo(); return 0; } file1.c • extern int x in file2.c stops the compiler complaining that x is an undeclared identifier - it is declared in file1.c extern int x; extern int y; void foo() { x++; y++; return; } file2.c

  5. 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. Structures • 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;

  7. struct stockItemStruct { int barCode; double price; int stockLevel; }; int main() { struct stockItemStructbeans; struct stockItemStructcornflakes; 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; } struct example type variables structure member reference

  8. struct 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 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 • 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 • 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 : b int main() { int x; int y = 2, z = 3; x= bigger( y-3, z-1); printf(" x = %i\n",x); return 0; }

  12. macro 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 * a int main() { int y, x = 2; y=square( x ); printf(" y = %i\n",y); // get 4 - correct y=square( x+1 ); printf(" y = %i\n",y); // get 5 - wrong should be 9 return 0; } • because square(x) becomes x * x • but square ( x +1 ) becomes x + 1 * x + 1which is 2x+1 not x2 • should be square ( a ) ( a ) * ( a )

  13. macro 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 • 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 • 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. pointers • 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. pointers - 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; } • x=3 does the following.. • x is stored at address 1003 (maybe), so.. • address value there1003 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

  18. dynamic 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. A program to - • get memory to store 20 integers in • store 0, 2, 4, 6, 8.. in it • print them out • release the memory dynamic memory example Output.. Offset 0 Value 0 Offset 1 Value 2 Offset 2 Value 4 Offset 3 Value 6 Offset 4 Value 8 Offset 5 Value 10 Offset 6 Value 12 Offset 7 Value 14 Offset 8 Value 16 Offset 9 Value 18 Offset 10 Value 20 Offset 11 Value 22 Offset 12 Value 24 Offset 13 Value 26 Offset 14 Value 28 Offset 15 Value 30 Offset 16 Value 32 Offset 17 Value 34 Offset 18 Value 36 Offset 19 Value 38 #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; }

  20. Pointer 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 arrays #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; } • 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

  22. functions with pointer arguments #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; } • 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

  23. 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 pointers #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; } Output.. 29358 26962 26500 24464 19169 18467 15724 11478 6334 41 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; }

  24. function and pointer exercise Write 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. suppose 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; pointers to structs

  26. pointers to structures exercise Re-use the employee struct Create a memory block of 100 employee structs Give them suitable random values Display them

More Related