APS105 Malloc and 2D Arrays Textbook Chapters 6.4, 10.2 Datatype Size Datatypes have varying size: char: 1B int: 4B double: 8B int sizeof(<type>): a builtin function that returns size of a type int x = sizeof(int); // x = 4 int x = sizeof(double); // x = 8 int x = sizeof(char); // x = 1 1
Arrays and Pointers Consider: int x[] = {9,7,8}; int *p = x; Memory Addr Value int *q = &x[2]; 0 4 x // value of *p is 9 4 16 p // value of *q is 8 8 24 12 q 16 9 x[0] x x[0] 20 7 x[1] p x[1] 24 8 x[2] q x[2] Pointer Arithmetic 4 2
Pointer Arithmetic Some operations allowed on pointers <pointer> + <int> // result is a pointer <pointer> - <int> // result is a pointer <pointer> - <pointer> // result is an int 5 Pointer Adding/Subtracting Result is scaled by the type size int *p; int *q = p + 2; // q = p + 2*sizeof(int) = p + 8 int *q = p 3; // q = p 3*sizeof(int) = p 12 Why is this useful? 3
Example of Addition to Pointer int x[] = {9,7,8}; int *p = &x[0]; // p points to x[0] p = p + 1; // want: p pts to x[1] // = p + 1*sizeof(int) = 16+1*4 = 20 Memory Addr Value 0 16 4 16 x p 8 12 16 9 20 7 24 8 x[0] x[1] x[2] Example of Subtraction from Pointer int x[] = {9,7,8}; int *p = &x[2]; // p points to x[2] p = p - 2; // want: p pts to x[0] // = p + 2*sizeof(int) = 24 2*4 = 16 Memory Addr Value 0 16 4 24 x p 8 12 16 9 20 7 24 8 x[0] x[1] x[2] 4
Subtracting Pointers Recall: <pointer2> - <pointer1> // result is an int Only valid if: both pointers point to parts of the same array the result is positive i.e., ptr2 points to a higher-addr location than ptr1 Result is divided by sizeof(<type>) Example: int x[] = {9,7,8}; int *p = &x[0]; int *q = &x[2]; int y = q p; // y = (q p) / sizeof(int) // = (24 16) / 4 = 2 Memory Addr 12 Value 0 16 4 16 8 24 16 9 20 7 24 8 x p q x[0] x[1] x[2] Comparing Pointers i.e, : <pointer1> < <pointer2> // result is an int Only valid if: both pointers point to parts of the same array the result is bool (true or false) can use ==,!=, <, >, <=, >= Example: int x[] = {9,7,8}; int *p = &x[1]; int *q = &x[2]; bool gt = q > p; // TRUE Memory Addr 12 Value 0 16 4 20 8 24 16 9 20 7 24 8 x p q x[0] x[1] x[2] 5
Pointers and Integers Cannot assign an integer value to a pointer exception: 0 (zero) example: int *p = 0; // is allowed NULL a predefined constant with the value zero example: int *p = NULL; // NULL is same as zero if (p) printf( huh? ); // this will not be executed Array and Pointer as Parameters void read(double list[], int size) { for (int i=0; i<size; i++) scanf( %lf,&list[i]); } void read(double *p, int size) { for (int i=0; i<size; i++) scanf( %lf, p+i); } 6
Dynamic Allocation 13 Dynamic Allocation We can create an array of a certain size double marks[100]; But what if we don t know #students? could assume a maximum number of students double marks[10000]; what s wrong with this approach? wastes lots of memory Better solution: dynamic allocation Can design data structures that change as needed. 7
Memory allocation functions #include <stdlib.h> malloc function Allocates a block of memory but does not initialize it. calloc function Allocates a block of memory and clears it. realloc function Resizes a previously allocated block of memory. These functions return a value of type (void *), which is a generic pointer; an address. Copyright 2008 W. W. Norton & Company. All rights reserved. 15 malloc to allocate storage Say a program will make use of an array of n elements, and n is initially not known, but is computed in the execution of the program. To allocate storage, first declare a pointer variable int *a; // a is a pointer to an int Then assign to the variable the first address of the block allocated by malloc: a = malloc (n * sizeof(int)); // this star is a multiplication Now a is really the array name Copyright 2008 W. W. Norton & Company. All rights reserved. 16 8
malloc to allocate storage the malloc function, therefore... means memory allocation reserves space in memory for a number of bytes Is called to allocate memory when you need it hence dynamically, at run-time, on-demand What if you ask for memory and there is none left? 17 Null Pointers Again... If a memory allocation function does not/cannot allocate space, it returns a null pointer. After the function returns a value, one must test if it is a null pointer. Example if ((p=malloc(300))==null){ /* problem! do something here*/ } Pointers can be tested like numbers (NULL pointers are false ) if (p==null), if (!p), if (p!=null), if(p) Copyright 2008 W. W. Norton & Company. All rights reserved. 18 9
Deallocating storage Memory allocation functions get their blocks from a storage pool called the memory heap. If the functions are carelessly called, the heap may run out of blocks and the functions start to return null pointers. If the program loses track of which blocks are being allocated, soon there will be a real-estate (memory) crisis. p = malloc(...); q = malloc(...); p = q; Copyright 2008 W. W. Norton & Company. All rights reserved. 19 Deallocating storage Avoid hogging memory. When you re done, release it using the free function. A program that leaves garbage behind is said to have a memory leak. A block of memory that is no longer accessible to a program is called garbage. Therefore... p = malloc(...); q = malloc(...); free(p); p = q; Copyright 2008 W. W. Norton & Company. All rights reserved. 20 10
Dangling pointers The function call free(p) deallocates the memory block that p points to, but it does not change p itself. If p, then, no longer points to a valid memory block, it is said to be a dangling pointer. Modifying that memory obviously leads to error; Note that many pointers may point to the same memory block If the memory block is deallocated, the pointers must be made to point Copyright 2008 W. W. Norton & Company. All rights reserved. 21 Marks Example w Malloc/Free #include <stdlib.h> int main(void) { } int numstudents; double *marks; printf( Pls enter #students: ); scanf( %d, &numstudents); marks = malloc(numstudents*sizeof(double));... // use marks[0]..marks[numstudents-1] free(marks); // release array 11
Multidimensional Arrays And Dynamic Allocation 23 We know that this is how it s stored... 0 1 2 3 0 8 7 9 2 1 9 3 8 4 2 5 1 3 6 const int ROWS = 3; const int COLS = 4; int A[ROWS][COLS] = {8,7,9,2,9,3, 8,4,5,1,3,6}; &A[i][j] == &A[0][0] + sizeof(int) * ((i * COLS) + j); == 8 + 4*(i*4 + j) Memory Addr Row Col Val 8 0 0 8 12 0 1 7 16 0 2 9 20 0 3 2 24 1 0 9 28 1 1 4 32 1 2 8 36 1 3 4 40 2 0 5 44 2 1 1 48 2 2 3 52 2 3 6 56 A[0][0] A[0][1] A[1][3] A[2][3] 12
MultiDimensional Array as Parameter Must specify all dimensions except first Examples: int f(int table[][cols]) // good int f(int table[rows][cols])//good int f(int table[][]) // not allowed Dynamic Allocation of 2D Array Dynamically allocate a ROWS x COLS Matrix first: lets visualize it: an (int **) arrays of int an array of (int *) 13
Dynamic Allocation of 2D Array Dynamically allocate a ROWS x COLS Matrix int **matrix; matrix = (int **)malloc(rows*sizeof(int *)); for (int i=0;i<rows;i++) { matrix[i] = (int *)malloc(cols*sizeof(int)); }... for (int i=0;i<rows;i++) free(matrix[i]); free(matrix); Dyn. Malloc d 2D Array as Parameter write a func f that sums all values of a 2D array int f(int **matrix, int rows, int cols) { } int sum = 0; for (int i=0;i<rows;i++) for (int j=0;j<cols;j++) sum += matrix[i][j]; return sum; 14