C Memory Simple Types Arrays Pointer to Pointer

  • Slides: 20
Download presentation
C - Memory • • • Simple Types Arrays Pointer to Pointer Multi-dimensional Arrays

C - Memory • • • Simple Types Arrays Pointer to Pointer Multi-dimensional Arrays Dynamic Memory Allocation 1

C-Memory 159. 234 POINTER TO A POINTER A third method is more common and

C-Memory 159. 234 POINTER TO A POINTER A third method is more common and uses a pointer to a pointer. char **p; We have to do more work to set this up as a 2 D array, but we have a lot more flexibility in the size of the array. The number of rows in the array is set first, by making p point to an array of pointers. p = (char **)malloc(rows*sizeof(char *)); each pointer is then set to point to an array of characters. for (i=0; i<row; i++) { p[i] = (char *)malloc(cols*sizeof(char)); } p is a pointer to a pointer p[i] is a string p[i][j] is a character 2

C-Memory 159. 234 POINTERS We can still use the [] operator to access elements

C-Memory 159. 234 POINTERS We can still use the [] operator to access elements of each array. We do not need to allocate the same number of characters to each string – the array does not have to be square. for (i=0; i<row; i++) { p[i] = (char *)malloc((i+1)*sizeof(char)); (i+1) } When we have finished with memory allocated from the heap, we must give it back. char *p; p = (char *)malloc(80*sizeof(char)); … free(p); In the case of pointers to pointers, we must be careful to free memory in the correct order. for (i=0; i<row; i++) { free(p[i]); } free(p); Do not access heap memory after it has been free'd. 3

C-Memory 159. 234 How does free know how much memory to release? malloc has

C-Memory 159. 234 How does free know how much memory to release? malloc has to remember how many bytes were allocated. How it does this is not specified, but one common way is to allocate an extra 4 bytes, at the start, that contain the size. If we write to p[-1] at any time, then our program will explode when we free(p) 4

C-Memory 159. 234 Local Variables Local variables are kept on a 'stack'. stack This

C-Memory 159. 234 Local Variables Local variables are kept on a 'stack'. stack This is created each time a function is called. The stack is destroyed when a return is executed. The stack is not set to zero each time it is created (too expensive) – and so local variables contain arbitrary data. Local variables need to be initialised. 5

C-Memory 159. 234 POINTERS A pointer may be on the stack – but what

C-Memory 159. 234 POINTERS A pointer may be on the stack – but what it points to may be on the heap. Failing to free heap memory before exiting a function will leave memory on the heap that no longer has a pointer pointing to it. This memory can never be recovered – it is called a memory leak Get into the habit of always freeing memory. Even when the program exits. 6

C-Memory 159. 234 POINTERS When a function wants to change the value of an

C-Memory 159. 234 POINTERS When a function wants to change the value of an actual parameter, an address must be passed to the function. For strings the syntax looks ok, because the name is itself an address: strcpy(s, “Napoleon"); … void strcpy(char *p, char *q) { inside strcpy we access the original using p[i]. To alter an integer the syntax is more clumsy twice(&i); … void twice(int *ip) { (*ip) = (*ip)*2; } 7

C-Memory 159. 234 POINTERS We have to be brave to alter a pointer! char

C-Memory 159. 234 POINTERS We have to be brave to alter a pointer! char *s; allocate_and_check(&s); … void allocate_and_check(char **p) { (*p) = (char *)malloc(80); if ((*p) == NULL) { … It is a lot easier to use return values. C++ tidies up the problems associated with malloc and free by introducing 2 new keywords, new and delete Reference parameters also are a new feature, to make it easier 8 to alter arguments.

C-Memory 159. 234 POINTERS & MULTIDIMENSIONAL ARRAYS int (*x)[20]; 2 D INTEGER ARRAY rather

C-Memory 159. 234 POINTERS & MULTIDIMENSIONAL ARRAYS int (*x)[20]; 2 D INTEGER ARRAY rather than (x+1) automatically takes into account the number of elements in an array int x[10][20]; x … First array (x +1) … Second array … *(*(x +2) + 5) Third array (x +2) *(x +2)+5 … … *(x +2) 9 See Address. Array 2. cpp

C-Memory vs. C++ Memory 159. 234 1 -D Array void array 1 D(){ int

C-Memory vs. C++ Memory 159. 234 1 -D Array void array 1 D(){ int cols=6; char *p; p = (char *) malloc(cols * sizeof(char)); strcpy(p, "hello"); cout << "p = " << p << dec << endl; free(p); } 10

C-Memory vs. C++ Memory 159. 234 1 -D Array allocation via function call int

C-Memory vs. C++ Memory 159. 234 1 -D Array allocation via function call int alloc 1 D(char **p, int elements){ (*p) = (char*) malloc(elements * sizeof(char)); if((*p) == NULL) return 0; else return 1; } 11

C-Memory vs. C++ Memory 159. 234 1 -D Array allocation via function call void

C-Memory vs. C++ Memory 159. 234 1 -D Array allocation via function call void array 1 D(){ int cols=5; char *p; int alloc 1 D(char **p, int elements){ (*p) = (char*) malloc(elements * sizeof(char)); p = (char *) malloc(cols * sizeof(char)); strcpy(p, "hello"); cout << "p = " << p << dec << endl; free(p); } if((*p) == NULL) return 0; else return 1; } char *p; if(alloc 1 D(&p, 5)) { strcpy(p, "hello"); cout << "at main(): p = " << p << endl; } free(p); 12

C-Memory vs. C++ Memory 159. 234 2 -D Array void array 2 D(){ int

C-Memory vs. C++ Memory 159. 234 2 -D Array void array 2 D(){ int rows=3; int cols=5; int **p; p = (int **) malloc(rows * cols * sizeof(int *)); for(int i=0; i < rows; i++){ p[i] = (int *) malloc(cols * sizeof(int)); } //add contents for(int i=0; i < rows; i++){ for(int j=0; j < cols; j++){ p[i][j] = i + j; cout << "p[" << i << "][" << j << "]= " << p[i][j] << endl; } } // free memory for(int i=0; i < rows; i++){ free(p[i]); } free(p); } 13

C-Memory vs. C++ Memory 159. 234 2 -D Array allocation via function call int

C-Memory vs. C++ Memory 159. 234 2 -D Array allocation via function call int alloc 2 D(char ***p, int rows, int cols){ (*p) = (char **) malloc(rows * cols * sizeof(char *)); if((*p) == NULL) return 0; else return 1; for(int i=0; i < rows; i++){ //(*p)[i] = (char *) malloc(cols * sizeof(char)); //OK *((*p)+i) = (char *) malloc(cols * sizeof(char)); //OK //(*p)+i) = (char *) malloc(cols * sizeof(char)); //ERROR! if( *((*p)+i) == NULL) return 0; else return 1; } } 14

C-Memory vs. C++ Memory 159. 234 2 -D Array allocation via function call void

C-Memory vs. C++ Memory 159. 234 2 -D Array allocation via function call void array 2 D(){ int rows=3; int cols=5; int **p; p = (int **) malloc(rows * cols * sizeof(int *)); for(int i=0; i < rows; i++){ p[i] = (int *) malloc(cols * sizeof(int)); } //add contents for(int i=0; i < rows; i++){ for(int j=0; j < cols; j++){ p[i][j] = i + j; cout << "p[" << i << "][" << j << "]= " << p[i][j] << endl; } } // free memory for(int i=0; i < rows; i++){ free(p[i]); } free(p); } int alloc 2 D(char ***p, int rows, int cols){ (*p) = (char **) malloc(rows * cols * sizeof(char *)); if((*p) == NULL) return 0; else return 1; for(int i=0; i < rows; i++){ //(*p)[i] = (char *) malloc(cols * sizeof(char)); //OK *((*p)+i) = (char *) malloc(cols * sizeof(char)); //OK //(*p)+i) = (char *) malloc(cols * sizeof(char)); //ERROR! if( *((*p)+i) == NULL) return 0; else return 1; } } 15

C-Memory vs. C++ Memory 159. 234 2 -D Array int alloc 2 D(char ***p,

C-Memory vs. C++ Memory 159. 234 2 -D Array int alloc 2 D(char ***p, int rows, int cols){ (*p) = (char **) malloc(rows * cols * sizeof(char *)); if((*p) == NULL) return 0; else return 1; for(int i=0; i < rows; i++){ //(*p)[i] = (char *) malloc(cols * sizeof(char)); //OK *((*p)+i) = (char *) malloc(cols * sizeof(char)); //OK //(*p)+i) = (char *) malloc(cols * sizeof(char)); //ERROR! char **s; if(alloc 2 D(&s, rows, cols)){ strcpy(s[0], "FILE“); strcpy(s[1], " EDIT“); strcpy(s[2], " QUIT“); for(int i=0; i < rows; i++){ cout << "s[" << i << "]= " << s[i] << endl; } } if( *((*p)+i) == NULL) return 0; else return 1; } } 16

C-Memory vs. C++ Memory 159. 234 New 1 -D Array allocation via function call

C-Memory vs. C++ Memory 159. 234 New 1 -D Array allocation via function call int alloc 1 D(char **p, int elements){ (*p) = (char*) malloc(elements * sizeof(char)); int new 1 D(char *&p, int elements){ p = new char[elements]; if((*p) == NULL) return 0; else return 1; if(p == NULL) return 0; else return 1; } } char *p; if(alloc 1 D(&p, 5)) { strcpy(p, "hello"); cout << "at main(): p = " << p << endl; } if(new 1 D(p, 5)) { strcpy(p, "hello"); cout << "at main(): p = " << p << endl; } free(p); delete [] p; 17

C-Memory vs. C++ Memory 159. 234 New 2 -D Array allocation via function call

C-Memory vs. C++ Memory 159. 234 New 2 -D Array allocation via function call int alloc 2 D(char ***p, int rows, int cols){ int new 2 D(char **&p, int rows, int cols){ (*p) = (char **) malloc(rows * cols * sizeof(char *)); p = new char*[rows]; if((*p) == NULL) return 0; else return 1; if(p == NULL) return 0; else return 1; for(int i=0; i < rows; i++){ //(*p)[i] = (char *) malloc(cols * sizeof(char)); //OK *((*p)+i) = (char *) malloc(cols * sizeof(char)); //OK //(*p)+i) = (char *) malloc(cols * sizeof(char)); //ERROR! for(int i=0; i < rows; i++){ if( *((*p)+i) == NULL) return 0; else return 1; p[i] = new char[cols]; if( p[i] == NULL) return 0; else return 1; } } 18

C-Memory vs. C++ Memory 159. 234 New 2 -D Array allocation via function call

C-Memory vs. C++ Memory 159. 234 New 2 -D Array allocation via function call char **s; if(alloc 2 D(&s, rows, cols)){ strcpy(s[0], "FILE“); strcpy(s[1], " EDIT“); strcpy(s[2], " QUIT“); if(new 2 D(s, rows, cols)){ strcpy(s[0], "FILE“); strcpy(s[1], " EDIT“); strcpy(s[2], " QUIT“); for(int i=0; i < rows; i++){ cout << "s[" << i << "]= " << s[i] << endl; } } //---------------for(int i=0; i < rows; i++){ free(s[i]); } free(s); for(int i=0; i < rows; i++){ cout << "s[" << i << "]= " << s[i] << endl; } } //---------------for(int i=0; i < rows; i++){ delete [] s[i]; } delete [] s; 19

Exercise char **s; if(alloc 2 D(&s, rows, cols)){ strcpy(s[0], "FILE“); strcpy(s[1], " EDIT“); strcpy(s[2],

Exercise char **s; if(alloc 2 D(&s, rows, cols)){ strcpy(s[0], "FILE“); strcpy(s[1], " EDIT“); strcpy(s[2], " QUIT“); for(int i=0; i < rows; i++){ cout << "s[" << i << "]= " << s[i] << endl; } } //---------------// view elements cout << "*(s+2) = " << *(s+2) << endl; cout << "*(*(s+2)) = " << *(*(s+2)) << endl; cout << "*(*(s+2)+2) = " << *(*(s+2)+2) << endl; cout << "(*(s+2)+2) = " << (*(s+2)+2) << endl; 20