From 7e0f021a9aec35fd8e6725e87e3313b101d26f5e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sun, 27 Jan 2008 11:37:44 +0100 Subject: Initial import (2.0.2-6) --- reference/C/CONTRIB/SAWTELL/c-lesson.4 | 313 +++++++++++++++++++++++++++++++++ 1 file changed, 313 insertions(+) create mode 100755 reference/C/CONTRIB/SAWTELL/c-lesson.4 (limited to 'reference/C/CONTRIB/SAWTELL/c-lesson.4') diff --git a/reference/C/CONTRIB/SAWTELL/c-lesson.4 b/reference/C/CONTRIB/SAWTELL/c-lesson.4 new file mode 100755 index 0000000..a6072e0 --- /dev/null +++ b/reference/C/CONTRIB/SAWTELL/c-lesson.4 @@ -0,0 +1,313 @@ + Lesson 3 + + Arrays and Pointers. + + You can allocate space for an array of elements at compile time with fixed + dimension sizes of any data type, even functions and structs. + So these are legal array definitions: + + char name[30]; /* An array of 30 signed characters. */ + char *strings[50]; /* 50 pointers to strings. */ + unsigned long int *(*func)()[20];/* An array of pointers to functions which +*/ + /* return pointers to unsigned long ints. */ + + You can declare a pointer to point at any type of data element, and as in + the array situation above functions and structs are included. + +struct ship +{ + char name[30]; + double displacement; /* in grammes */ + float length_of_water_line; /* in meters */ + unsigned short int number_of_passengers; + unsigned short int number_of_crew; + }; + + So using the ship concept from Lesson 2 you can declare a pointer to point + at one of the ship structs in an array. + +struct ship *vessel_p; + + Note the use of the suffix "_p". + This is my way of reminding myself that the variable is a pointer. + +struct ship fleet[5]; /* This allocates enough storage for 5 ships' info. +*/ + + Now lets set the pointer to point at the first vessel in the fleet. + + vessel_p = fleet; + + This pointer can be made to point at other ships in the fleet by + incrementing it or doing additive arithmetic on it: + + vessel_p++; /* point a the next ship in the fleet array. */ + vessel_p = fleet + 3; + + Also we can find out the index of the ship in the fleet at which we are + pointing: + + i = vessel_p - fleet; + + It is also legal to find out the separation of two pointers pointing at + elements in an array: + + d = vessel_p - another_vessel_p; /* This gives the separation in elements. */ + + So summarising, pointers may be, incremented, decremented, and subtracted + one from another or have a constant subtracted from them. Any other + mathematical operation is meaningless and not allowed. + + Assembler programmers should note that while the pointer variables contain a + byte machine address, when the arithmetic is done using pointers the +compiler + also issues either a multiply or a divide as well as the add or subtract + instruction so that the result is ALWAYS expressed in elements rather than + bytes. Have a go and write yourself a trivial little program, and have a + look at the compiler ouput code. Lesson 1 told you how! + + When using a pointer to reference a structure we have to use a "pointer + offset" operator in order to access the member of the struct we require: + + vessel_p = fleet; + + vessel_p->name = "Queen Mary"; + vessel_p->displacement = 97500000000.0; + vessel_p->length_of_water_line = 750.0 + vessel_p->number_of_passengers = 3575; + vessel_p->number_of_crew = 4592; + + Remember: + + It's a "." when accessing a struct which is in storage declared in + the program. + + It's a "->" when accessing a struct at which a pointer is pointing. + + Initialisation of arrays. + + 'C' has the facility to initialise variables in a program script. + + Some examples: + + char *qbf = "The quick brown fox jumped over the lazy dogs back"; + + int tic_tac_toe[3][3] = + { + { 1, 2, 3 }, + { 4, 5, 6 }, + { 7, 8, 9 } + }; + + struct ship fleet[2] = + { + { "Queen Elizabeth", 97500000000.0, 750.0, 3575, 4592 }, + { "Queen Mary", 115000000000.0, 875.0, 4500, 5500 } + }; + + Take a careful note of where the commas and semi-colons go ( and don't go )! + + Initialised Tables of Indeterminate Length. + + One nice feature 'C' offers is that it is able to calculate + the amount of storage required for a table by 'looking' at the number + of initialisers. + +char *verse[] = +{ + "On top of the Crumpetty Tree", + "The Quangle Wangle sat,", + "But his face you could not see,", + "On account of his Beaver Hat.", + "For his Hat was a hundred and two feet wide.", + "With ribbons and bibbons on every side,", + "And bells, and buttons, and loops, and lace,", + "So that nobody ever could see the face", + "Of the Quangle Wangle Quee." + NULL + }; + + Note the * character in the definition line. This means that we are going + to make an array of pointers to variables of type char. As there is no + number between the [ ] characters the compiler calculates it for us. + With this kind of set-up it is nice and easy to add extra information + to the table as program development proceeds. The compiler will calculate + the new dimension for you. The point to remember is that the program has to + know - from the contents of the table - that it has come to the end of the + table! So you have to make a special entry which CANNOT under any + circumstances be a real data element. We usually use NULL for this. + The other way is to calculate the size of the table by using the sizeof + operator - Note that although use of sizeof looks like a function call + it is in fact an intrinsic operator of the language. The result is + available at compile time. So one can say:- + + #define SIZE_OF_VERSE sizeof verse + + There is one final initialised data type, the enum. It is a fairly recent + addition to the language. + + enum spectrum { red, orange, yellow, green, blue, indigo, violet } colour; + + In this construct the first symbol is given the value of 0 and for each + following symbol the value is incremented. It is however possible to assign + specific values to the symbols like this: + + enum tub + { anorexic = 65, + slim = 70, + normal = 80, + fat = 95, + obese = 135 + }; + + Some compilers are bright enough to detect that it is an error if an + attempt is made to assign a value to an enum variable which is not in + the list of symbols, on the other hand many are not. Take care! In + practice there is little difference between the enum language construct + and a number of define statements except perhaps aesthetics. Here is + another trivial program which demonstrates the use of enum and a + pre-initialised array. + +#include + +enum spectrum { red, orange, yellow, green, blue, indigo, violet } colour; + +char *rainbow[] = { "red", "orange", "yellow", "green", + "blue", "indigo", "violet" }; + +main() +{ + for ( colour = red; colour <= violet; colour++ ) + { + printf ( "%s ", rainbow[colour]); + } + printf ( "\n" ); + } + + The output of which is ( not surprisingly ): + +red orange yellow green blue indigo violet + + One quite advanced use of initialised arrays and pointers is the jump or + dispatch table. This is a efficient use of pointers and provides a very much + better ( In my opinion ) method of controlling program flow than a maze + of case or ( heaven forbid ) if ( ... ) goto statements. + + Please cut out this program, read and compile it. + ------------------------------------------------------------------------ + +char *ident = "@(#) tellme.c - An example of using a pointer to a function."; + +#include +#include +#include + +/* +These declarations are not in fact needed as they are all declared extern in +math.h. However if you were to use routines which are not in a library and +therefore not declared in a '.h' file you should declare them. Remember you +MUST declare external routines which return a type other than the int type. + +extern double sin (); +extern double cos (); +extern double tan (); +extern double atof (); +*/ + +struct table_entry +{ + char *name; /* The address of the character string. */ + double (*function)(); /* The address of the entry point of the function. */ + }; + +typedef struct table_entry TABLE; + +double help ( tp ) +TABLE *tp; +{ printf ( "Choose one of these functions:- " ); + fflush ( stdout ); + for ( ; tp -> name; tp++ ) printf ( "%s ", tp -> name ); + printf ( "\nRemember the input is expressed in Radians\n" ); + exit ( 0 ); + return ( 0.0 ); /* Needed to keep some nit-picking dumb compilers happy! */ + } + +/* + * This is the array of pointers to the strings and function entry points. + * Is is initialised at linking time. You may add as many functions as you + * like in here PROVIDED you declare them to be extern, either in some .h + * file or explicitly. + */ + +TABLE interpretation_table [ ] = +{ + { "sin", sin }, + { "tan", tan }, + { "cos", cos }, + { "help", help }, + { NULL, NULL } /* To flag the end of the table. */ + }; + +char *output_format = { "\n %s %s = %g\n" }; +extern int errno; +extern void perror(); + +main( argc, argv ) +int argc; +char **argv; +{ + TABLE *tp; + double x, answer; + + if ( argc > 3 ) + { + errno = E2BIG; + perror ( "tellme" ); + exit ( -1 ); + } + + for (;;) /* This is the way to set up a continuous loop. */ + { + for ( tp = interpretation_table; + ( tp -> name && strcmp ( tp -> name, argv[1] )); + tp++ + ) ; /* Note use of empty for loop to position tp. */ + + if ( tp -> function == help ) (*tp -> function )( interpretation_table ); + if ( tp -> name == NULL ) + { + printf ( "Function %s not implemented yet\n", argv[1] ); + exit ( 1 ); + } + break; /* Leave the loop. */ + } + + x = atof ( argv[2] ); /* Convert the character string to a double. */ + answer = ( *tp -> function )( x );/* Execute the desired function. */ + printf ( output_format, /* Pointer to printf()'s format string. */ + argv[1], /* Pointer to the name of the function. */ + argv[2], /* Pointer to the input number ascii string. */ + answer /* Value ( in double floating point binary ) */ + ); + } + +Copyright notice:- + +(c) 1993 Christopher Sawtell. + +I assert the right to be known as the author, and owner of the +intellectual property rights of all the files in this material, +except for the quoted examples which have their individual +copyright notices. Permission is granted for onward copying, +but not modification, of this course and its use for personal +study only, provided all the copyright notices are left in the +text and are printed in full on any subsequent paper reproduction. + +-- + +----------------------------------------------------------------------+ + | NAME Christopher Sawtell | + | SMAIL 215 Ollivier's Road, Linwood, Christchurch, 8001. New Zealand.| + | EMAIL chris@gerty.equinox.gen.nz | + | PHONE +64-3-389-3200 ( gmt +13 - your discretion is requested ) | + +----------------------------------------------------------------------+ -- cgit v1.2.3-54-g00ecf