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

Info icon This 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 [email protected] . 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

{[ snackBarMessage ]}

What students are saying

  • Left Quote Icon

    As a current student on this bumpy collegiate pathway, I stumbled upon Course Hero, where I can find study resources for nearly all my courses, get online help from tutors 24/7, and even share my old projects, papers, and lecture notes with other students.

    Student Picture

    Kiran Temple University Fox School of Business ‘17, Course Hero Intern

  • Left Quote Icon

    I cannot even describe how much Course Hero helped me this summer. It’s truly become something I can always rely on and help me. In the end, I was not only able to survive summer classes, but I was able to thrive thanks to Course Hero.

    Student Picture

    Dana University of Pennsylvania ‘17, Course Hero Intern

  • Left Quote Icon

    The ability to access any university’s resources through Course Hero proved invaluable in my case. I was behind on Tulane coursework and actually used UCLA’s materials to help me move forward and get everything together on time.

    Student Picture

    Jill Tulane University ‘16, Course Hero Intern