350 likes | 362 Views
Homework. Finishing up K&R Chapter 6 today Also, K&R 5.7 – 5.9 (skipped earlier). typedef, K&R 6.7. typedef creates a new name for existing type typedef int Boolean; typedef char *String; Does not create a new type in any real sense No new semantics for the new type name!
E N D
Homework • Finishing up K&R Chapter 6 today • Also, K&R 5.7 – 5.9 (skipped earlier)
typedef, K&R 6.7 • typedef creates a new name for existing type typedef int Boolean; typedef char *String; • Does not create a new type in any real sense • No new semantics for the new type name! • Variables declared using new type name have same properties as variables of original type
typedef • Could have used typedef in section 6.5 like this: typedef struct tnode *treeptr; typedef struct tnode { char *word; int count; treeptr left; treeptr right; } treenode;
typedef • Then, could have coded talloc ( ) as follows: treeptr talloc(void) { return (treeptr) malloc(size of(treenode)); }
typedef • Used to provide clearer documentation: treeptr root; versus struct tnode *root; • Used to create machine independent variable types: typedef int size_t; /* size of types */ typedef int ptrdiff_t; /* difference of pointers */
Unions, K&R 6.8 • A Union is a variable that may hold objects of different types (at different times or for different instances of use) union u_tag { int ival; float fval; char *sval; } u;
Unions • A union will be allocated enough space for the largest type in the list of possible types • Same as a struct except all members have a zero offset from the base address of union u ival fval *sval
Unions • The operations allowed on unions are the same as operations allowed on structs: • Access a member of a union union u_tag x; x.ival = … ; • Assign to union of the same type union u_tag y; x = y;
Unions(cont’d) • Create a pointer to / take the address of a union union u_tag x; union u_tag *px = &x; • Access a member of a union via a pointer px->ival = … ;
Unions • Program code must know which type of value has been stored in a union variable and process using correct member type • DON’T store data in a union using one type and read it back via another type in attempt to get the value converted between types x.ival = 12; /* put an int in union */ float z = x.fval; /* don’t read as float! */
Bit-Fields, K&R 6.9 • Bit fields are used to get a field size other than 8 bits (char), 16 bits (short on some machines) or 32 bits (long on most machines) • Allows us to “pack” data one or more bits at a time into a larger data item in memory to save space, e.g. 32 single bit fields to an int • Can use bit fields instead of using masks, shifts, and or’s to manipulate groups of bits
Bit-Fields • Uses struct form: struct { unsigned int flg1 : 1; /* called a “bit field“ */ unsigned int flg2 : 1; /* ": 1" "1 bit in length " */ unsigned int flg3 : 2; /* ": 2" "2 bits in length" */ } flag; /* variable */ • Field lengths must be an integral number of bits
Bit-Fields • Access bit fields by member name same as any struct – just limited number of values flag.flg1 = 0; /* or = 1; */ flag.flg3 = 0; /* or = 1; = 2; =3; */
Bit-Fields • Minimum size data item is implementation dependent, as is order of fields in memory • Don’t make any assumptions about order!! • Sample memory allocation: flags 2 1 1 flags.flg3 flags.flg2 flags.flg1
Multi-Dimensional Arrays • Declare rectangular multi-dimensional array char array [2] [3]; /* array [row] [column] */ • It is the same as a one dimensional array with each element being an array • NOTE THAT array [2, 3] IS INCORRECT! • The rightmost subscript varies fastest as one looks at how data lies in memory array [0] [0], array [0] [1], array [0] [2], array [1] [0], array [1] [1], array [1] [2]
Multi-Dimensional Arrays • Example of converting a month & day into a day of the year for either normal or leap years static char daytab[2] [13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; • Use a second row of day counts for leap year rather than perform a calculation for days in February daytab[1] [1] is 31 same as daytab[0] [1] daytab[1] [2] is 29 not same as daytab [0] [2]
Multi-Dimensional Arrays • The array declared as char daytab [2] [13] can be thought of as: char (daytab [2]) [13]; /* see pg. 53 */ • Each one dimensional array element (daytab[0], daytab[1]) is like array name - as if we declared: char xx [13]; char yy [13] Where xx is daytab[0] and yy is daytab[1] • daytab [0] is in memory first, and then daytab [1]
Multi-Dimensional Arrays • daytab[0] and daytab[1] are arrays of 13 chars • Now recall duality of pointers and arrays: (daytab [0]) [13] (*daytab) [13] (daytab [1]) [13] (*(daytab+1)) [13] • daytab is a pointer to an array of elements each of size=13 chars
Multi-Dimensional Arrays • But, these two declarations are not allocated in memory the same way: char a [10] [20] 200 char-sized locations char (*b) [20] 1 pointer to an array of elements each is 20 chars • For the second declaration, code must set the pointer equal to an already defined array or use malloc to allocate new memory for an array. e.g. char (*b) [20] = a; or char (*b) [20] = (char (*) [ ]) malloc(200);
Multi-Dimensional Arrays char a [10] [20]; a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars char (*b) [20] = a; A pointer to unspecified number of 20 char arrays char (*b) [20] char (*b) [20] = (char (*) [ ]) malloc(200); 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars 20 chars
Example of Pointer to a Multi-Dimensional Array int grid[320][240]; int (*grid_ptr)[240]; int doSomethingWithGrid(int (*array)[240]); int main() { grid_ptr = grid; /* set grid_ptr to point at grid */ doSomethingWithGrid(grid_ptr); }
Review • Declarations/Definitions, K&R pg. 9, 210 • In C, all variables must be declared before they are used Complies with ANSI C • ALWAYS before any executable statements within the same block { … } • Declarations specify the interpretation given to each identifier • Declarations that reserve storage are called Definitions
Declarations / Definitions Memory Allocated? int i; char array [10]; char array [ ] = {“ABCDEF”}; char *word; int *ip = &i; void foo (int, char *); void foo (int i, char *word) { … }
Declarations / Definitions Memory Allocated? struct foobar { int i; char * word; }; struct foobar *foo; struct foobar three = {3, “three”};
Declarations / Definitions Memory Allocated? union foobar { int i; char * word; }; union foobar *foo; typedef int boolean_t;
Character pointers and Functions • Difference between: char amessage[] =“now is the time”; char *pmessage = “now is the time”; 16 bytes amessage: now is the time\0 4 bytes 16 bytes pmessage: now is the time\0
2-dimensional arrays • Difference between: char *name[] ={“Illegal month”, “Jan”, “Feb”, “Mar”}; char aname[][15]={“Illegal month”, “Jan”, “Feb”, “Mar”}; name: Illegal month\0 Jan\0 Feb\0 Mar\0 aname: Illegal month\0 Jan\0 Feb\0 Mar\0 0 15 30 45
Manipulating structs #include <stdio.h> struct item { char *word; struct item *link; }; struct item *addlist(struct item *, struct item *); void printlist(struct item *);
Manipulating structs int main () /* structs built by main program */ { /* all variables are automatic – on stack */ struct item cat = {"cat“,NULL}, dog = {"dog“,NULL}, frog = {"frog“,NULL}; struct item *list = NULL; list = addlist(list, &cat); list = addlist(list, &dog); list = addlist(list, &frog); printlist(list); return 0; } /* all memory used is freed upon return */
Manipulating structs struct item *addlist(struct item *root, struct item *animal) { animal->link = root; return animal; } void printlist(struct item *root) { for ( ; root != NULL; root = root->link) printf("%s\n", root->word); }
Manipulating structs - using dynamic memory int main () /* structs built in addlist function */ { /* variables point to dynamic memory */ struct item *list = NULL; list = addlist(list, "cat"); /* uses malloc */ list = addlist(list, "dog"); /* uses malloc */ list = addlist(list, "frog"); /* uses malloc */ printlist(list); list = dellist(list); /* must free all memory used */ return 0; }
Manipulating structs struct item *addlist(struct item *root, char *wd) { struct item *new = (struct item *) malloc(sizeof(struct item)); new->word = (char *) malloc(strlen(wd)+1); strcpy(new->word, wd); new->link = root; return new; }
NULL “cat” word pointer word pointer word pointer link pointer link pointer link pointer “dog” “frog” struct list
Manipulating structs /* Delete the list from the end of the list */ struct item *dellist(struct item *root) { struct item *temp; while (root != NULL) { free((void *) root->word); temp = root->link; /*before doing free we should save a copy in a temporary space */ free((void *) root); root = temp; } return root; }
Example of pointer to functions typedef struct cmdtag { char *cmdtoken; /* md or whatever--char string to invoke cmd */ int (*cmdfn)(struct cmdtag *, char *); /* function to call for this cmd */ char *help; /* helpstring for cmd */ } Cmd; Cmd cmds[] = {{"md", mem_display, "Memory display: MD <addr>"}, {"s", stop, "Stop" }, {NULL, NULL, NULL}}; main(){ int cnum; char linebuf[100]; … done = cmds[cnum].cmdfn(&cmds[cnum], linebuf); … } int mem_display(Cmd *cp, char * arguments) {…} int stop(Cmd *cp, char *arguments) {…}