Pointers are used to keep track of dynamic memory. Memory Allocation: malloc().
○ Additional memory to create dynamic data ... The anatomy of a malloc() call.
57:017 Computers in Engineering—C Dynamic Memory Allocation
Dynamic Memory Allocation z
We often don’t know at compile time how much data space a program will need: e.g. may not know how large an array will be needed to hold input data
z
z
Solution 1: Use arrays of maximum possible size that we would encounter Very wasteful, wasteful as we require lots and lots of memory that we may never use Total amount of memory required by the program may exceed acceptable limit
z z
z
Solution 2: Dynamic memory We can create arrays ( or other data structures) “on the fly”, asking for memory as we need it and releasing it for possible reuse when finished Pointers are used to keep track of dynamic memory
z
z
Memory Allocation: malloc()
Using malloc() z
z
z
z z
Additional memory to create dynamic data structures must be requested from the system. The function malloc() () allocates a requested number of bytes from the system to the program Returns a generic pointer to the allocated memory The program can cast this pointer to any desired data type
sizeof() operator z z
z
Determines the size in bytes of a data type When an array name is specified as the argument, returns the number of bytes in the array Typically: z z z z
Later, we will use sizeof() to determine the size of more complex data types-e.g. structures
Must request a specific number of bytes from malloc() z
z
Use sizeof operator to get bytes required by data type
Must cast returned pointer to correct type #include int *xPtr; /* Allocate space for 100 int values */ xPtr = (int *) malloc(100*sizeof(int)); *xPtr = 3; /* Sets first int to 3 */ xPtr[99] = 2; /* Sets 100th int to 2 */ *(xPtr + 99) = 2; /* Same thing as above */
The anatomy of a malloc() call pointer to desired type
total number of bytes to be allocated
xPtr = ( (int *) ) malloc( ( 100*sizeof(int) ( ) ) ); cast the pointer returned by malloc() to the desired pointer type
number of elements to be allocated
number of bytes per element
1
The anatomy of a malloc() call
Additonal malloc() details Returns NULL if memory could not be allocated
double *dPtr; dPtr = (double *) malloc(100*sizeof(double)); if (dPtr == NULL) { printf("Could not allocate memory\n"); …
What is going on in the computer memory? xPtr ÅÆ
Address
Value
6000
8000
…..
…..
8000
unknown
*(xPtr+1), xPtr[1] ÅÆ
8004
10
…..
Should always use sizeof() to get the size of a data type
z
*xPtr, xPtr[0] ÅÆ
z
Systems vary in data type and structure space usage, even in standard data types like int
…..
*(xPtr+98), xPtr[98] ÅÆ
8392
unknown
*(xPtr+99), xPtr[99] ÅÆ
8396
unknown
&(xPtr[98]) is memory address of xPtr[98] and is equal to 8392
Another memory allocation function: calloc() number of elements
size of an element
Deallocating Memory with free() z
xPtr = (int *) calloc( 100, sizeof(int) ); z z
Note: two parameters Main difference between malloc() and calloc() is that calloc() initializes the allocated memory to all zeros.
z
When a dynamically allocated data structure is no longer needed, it can be given back to the system for reallocation, using the free() function int *xPtr; xPtr = (int *)) malloc(100 malloc(100*sizeof(int)); sizeof(int)); .... free(xPtr); After free(), the values pointed to by xPtr are no longer valid Using xPtr without reinitializing may result in strange problems
z
Returning a Dynamically Allocated Array Assume that you want to write a subroutine to allocate an array and return the array. There are two ways to return the array:
z
z 1 1.
2.
z
Use a return statement to return the address of the array. Return the address of the array by reference.
You need to decide which of the two methods you are going to use before you can write you subroutine.
Example: Returning a Dynamically Allocated Array Problem Statement: Write a subroutine that allocates an N element 1D array of integers, initializes the array from 0 to N-1, and returns the array. y Start this problem by listing the inputs and outputs of the subroutine
z
z z z
Inputs: int size = number of elements of array Outputs: int * array = a 1D array of ints initialized from 0 to N-1.
2
Example: Returning a Dynamically Allocated Array Decide how the input and output variables will be passed to and from the subroutine.
z z z
Example: Case 1, Return array using return statement int * InitArray(int size){ int * array; int i;
Input variables can be passed by value or by reference Output variable can be returned using a return statement or by reference.
array = (int *) malloc(size*sizeof(int)); if (array == NULL){ printf(“Error: Unable to allocate array\n”); exit(-1); }
Input variable “size” does not need to be changed so pass by value Output variable “array” can be returned using a return statement or by reference.