CS110_08bbOPTIONAL-Ptr2Ptrs

CS110_08bbOPTIONAL-Ptr2Ptrs - EECS110: 8bb An Ugly...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: EECS110: 8bb An Ugly Practice: Pointers to Pointers Jack Tumblin jet@cs.northwestern.edu . 1 (Recall) Data Nesting: list of strings Dynamic Array of structs with (dyn. alloc'd)pointers to chars typedef struct stringT // Define a `message' struct { char *pTxt; // dyn. alloc'd char buffer Make an dynamic array int size; // max# of chars allowed in buffer of 10 `string' objects, } stringT; int main(void) and fill with messages { stringT *pMsgList; // dyn. alloc'd array of strings int k; //???? What would you do to allocate the pMsgListArray ???? for(k=0; k<10; k++) { pMsgList[k].size = 81; pMsgList[k].pTxt = // get memory for string k (char *)malloc(pMsgList[k].size*sizeof(char)); } strncpy(pMsgList[0].pTxt,"Press zero now",80); ... 2 set their buffer sizes, Sensible: lists of lists of lists... You can use nested structures, step-by-step: structures stringT: structure for a dyn. alloc'd SET of chars, paragT: structure for a dyn. alloc'd SET of stringT, chapT: structure for a dyn. alloc'd SET of paragT, bookT: structure for a dyn. alloc'd SET of chapT. Pointers-to-pointers-to... ; this will work too! SEEMS compact, SEEMS efficient, SEEMS to show a programmer's ultra-cleverness. But what a mess! Understand it, but don't use it... it 3 (Recall) Array of Strings Declare an array of pointers, Whose elements point to strings: And array index chooses a string. char *name[3] = {"Francois","James","Mahesh"}; char *tmp; printf("%s,%s,%s\n",name[0],name[1],name[2]); tmp = name[0]; // swap names 0,2 name[0] = name[2]; name[2] = tmp; printf("%s,%s,%s\n",name[0],name[1],name[2]); 4 (Recall) Array of Strings Declare an array of pointers, Whose elements point to strings: And array index chooses a string. char *name[3] = {"Francois","James","Mahesh"}; char *tmp; printf("%s,%s,%s\n",name[0],name[1],name[2]); tmp = name[0]; // swap names 0,2 name[0] = name[2]; name[2] = tmp; printf("%s,%s,%s\n",name[0],name[1],name[2]); 5 (Recall) Array of Strings Declare an array of pointers, Whose elements point to strings: And array index chooses a string. char *name[3] = {"Francois","James","Mahesh"}; char *tmp; printf("%s,%s,%s\n",name[0],name[1],name[2]); tmp = name[0]; // swap names 0,2 name[0] = name[3]; name[3] = tmp; printf("%s,%s,%s\n",name[0],name[1],name[2]); RESULT: > Francois,James,Mahesh > Mahesh,James,Francois 6 Pointers to Pointers int main() { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for a re-sizable list of pointers: Declare pointer for a list of... // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 7 Pointers to Pointers int main() { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for a re-sizable list of pointers: Declare pointer for a list of... // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 8 Pointers to Pointers int main() { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for a re-sizable list of pointers: Get space for 3 (pointers-to-char) // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 9 Pointers to Pointers int main() { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for a re-sizable list of pointers: Init: point elements to string constants // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 10 Pointers to Pointers int main() { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for a re-sizable list of pointers: Use index to select string // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 11 Pointers to Pointers int main() { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for a re-sizable list of pointers: A second index selects chars within string // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 12 Pointers to Pointers int main() memory, not **name !!) { char **name; (not in book) But array sizes are fixed: let's use dynamic allocation for to reserved (name points a re-sizable list of pointers: Release list memory when done // pointer-to-(pointers-to char) name = (char **)malloc(3*sizeof(char *)); name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; printf("%s,%s,%s,",name[0],name[1],name[2]); printf("%c,%c,%c!\n", name[0][0],name[1][0],name[2][0]); free(name); }RESULT: Zero,One,Two,Z,O,T! 13 Pointers to Pointers What's going on: (not in book) name = (char **)malloc(3*sizeof(char *)); (pointer to list of char pointers) pointers "Reserve a block of memory big enough for 3 char pointers; Then return a pointer to it" name ... name[0] name[1] name[2] ... (Each element is a char pointer; pointer 0th pointer is `name[0]', 1st pointer is `name[1]', etc. ) 14 Pointers to Pointers What's going on: name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; (pointer to list of char pointers) pointers (not in book) "Aim each pointer in the list we made at a string constant held in memory somewhere" somewhere (char pointers) pointers name ... name[0] name[1] name[2] ... (chars) char ... + $ 3 Z e r o \0 8 2 O n e \0 + 4 6 T w o \0 - . . . 15 Pointers to Pointers What's going on: name[0] = "Zero"; name[1] = "One"; name[2] = "Two"; (pointer to list of char pointers) pointers (not in book) "Aim each pointer in the list we made at a string constant held in memory somewhere" somewhere (char pointers) pointers name ... name[0] name[1] name[2] ... (chars) char ... + $ 3 Z e r o \0 8 2 O n e \0 + 4 6 T w o \0 - . . . name[0][0] name[0][2] name[0][2] 16 Pointers to Pointers What's going on: free(name); (not in book) "Release block of memory we reserved at pointer `name'" (pointer to list of char pointers) pointers name (char pointers) pointers ... name[0] name[1] name[2] ... (chars) char ... + $ 3 Z e r o \0 8 2 O n e \0 + 4 6 T w o \0 - . . . 17 Pointers to Pointers int main() { double **grid; int i,rmax,cmax; (not in book) Make Multi-dimensional grids of numbers in same way! Declare ptr. to list of pointers, // pointer-to-pointer-to-double // size of grid grid = (double **)malloc(rmax*sizeof(double *)); for(i=0; i<rmax; i++) //rmax pointers-to-double { //where you malloc cmax doubles grid[i]=(double *)malloc(cmax*sizeof(double)); } . . . COMPUTE! . . . use grid[r][c] . . . for(i=0; i<rmax; i++) { free(grid[i]); } free(grid); 18 } Pointers to Pointers int main() { double **grid; int i,rmax,cmax; (not in book) Make Multi-dimensional grids of numbers in same way! // pointer-to-pointer-to-double // size of grid grid = (double **)malloc(rmax*sizeof(double *)); for(i=0; i<rmax; i++) //rmax pointers-to-double { //where you malloc cmax doubles grid[i]=(double *)malloc(cmax*sizeof(double)); } . . . COMPUTE! . . . use grid[r][c] . . . for(i=0; i<rmax; i++) { free(grid[i]); Make a block of rmax } pointers-to-float free(grid); 19 } Pointers to Pointers int main() { double **grid; int i,rmax,cmax; (not in book) Make Multi-dimensional grids of numbers in same way! // pointer-to-pointer-to-double // size of grid grid = (double **)malloc(rmax*sizeof(double *)); for(i=0; i<rmax; i++) //rmax pointers-to-double { //where you malloc cmax doubles grid[i]=(double *)malloc(cmax*sizeof(double)); } . . . COMPUTE! . . . use grid[r][c] . . . for(i=0; i<rmax; i++) { free(grid[i]); Make a block of } cmax floats for each free(grid); 20 } pointer-to-float Pointers to Pointers int main() { double **grid; int i,rmax,cmax; (not in book) Make Multi-dimensional grids of numbers in same way! // pointer-to-pointer-to-double // size of grid grid = (double **)malloc(rmax*sizeof(double *)); for(i=0; i<rmax; i++) //rmax pointers-to-double { //where you malloc cmax doubles grid[i]=(double *)malloc(cmax*sizeof(double)); } . . . COMPUTE! . . . use grid[r][c] . . . for(i=0; i<rmax; i++) Done? Reverse the process; { free(grid[i]); free each block of floats, then } free block of pointers-to-float free(grid); 21 } Pointers to Pointers (not in book) grid = (double **)malloc(rmax*sizeof(double *)); "Reserve block of memory for rmax pointers-to-double" double (pointer to list of double pointers) pointers grid (rmax double pointers) pointers ... grid[0] grid[1] grid[2] ... 22 Pointers to Pointers (not in book) grid = (double **)malloc(rmax*sizeof(double *)); for(i=0; i<rmax; i++) { grid[i]=(double *)malloc(cmax*sizeof(double)); } (pointer to list of double pointers) pointers grid ... "For each pointer we made, reserve a block of memory to hold cmax doubles" (rmax double pointers ==> ) grid[0] grid[1] grid[2] ... (block of cmax doubles==>) 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . . 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . . 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . . 23 Pointers to Pointers (not in book) grid[1][2] = radius*(sin(x) + cos(y)...); "Access the x-th pointer, and get it's y-th double value" value (pointer to list of double pointers) pointers grid (xmax double pointers ==> ) ... r grid[0] grid[1] grid[2] ... (block of cmax doubles==>) 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . . 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . . grid[1][2] grid[r][c] c 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . 2 . 0 0 3 . 6 2 4 3 3 . 1 9 9 9 . 0 2 5 7 6 . 3 2 1 . . . 24 Ugly: pointers-to-pointers GOOD: VERY compact notation, VERY efficient memory usage, Permits multidimensional dynamically alloc'd arrays. (and ... ? ... I can't find anything else good about them). BAD: needlessly confusing; a debug nightmare Subtle, confusing, almost-ambiguous syntax; Difficult to modify, understand, or use such code, Fragile: intolerant of error, complex memory bounds, may hide multi-dimensional, cross-dimensional errors... NESTED STRUCTS ARE MUCH EASIER, CLEARER... 25 Example: 3-D Array of Numbers Define one struct for each dimension: rowT: a 1D re-sizeable array of floats rowT matrixT: a 1D re-sizeable array of rowT structs matrixT brickT: a 1D re-sizeable array of matrixT structs brickT typedef typedef typedef struct struct struct rowT { float *pVal; int rowSize;} rowT; matrixT{ rowT *pRow; int colSize;} matrixT; brickT{matrixT *pMat; int stakSize} brickT; // Support functions: void rowSizer(rowT *pR, int Rsiz); // allocate Rsiz floats. void matrixSizer(matrixT *pM, int Rsiz, Csiz); // Allocate memory at pM for Csiz rowT structs; for // each one, call rowSizer() to allocate Rsiz floats void brickSizer(brickT *pB, int Rsiz, int Csiz, int Ssiz); // Allocate memory at pB for Ssiz matrixT structs; for // each one, call matrixSizer() to alloc Rsiz,Csiz floats 26 ...
View Full Document

Ask a homework question - tutors are online