We can use pointers to request memory on the fly at runtime.
malloc()
: Allocate block of memory.free()
: Deallocate that block of memory.free
ing it (to avoid accidentally dereferencing a junk value).Note: Check after allocation that memory was indeed allocated.
- Done by seeing if your pointer points to a valid memory location instead of NULL.
Example: Dynamically creating a single-dimensional array
#include <stdio.h> #include <stdlib.h> int main() { int n, *ptr = 0; // Prompt user for array length ("Enter number of elements: "); printf("%d", &n); scanf// Dynamic memory allocation using malloc() = malloc(n*sizeof(int)); ptr // Exit if no memory was allocated if(ptr == NULL) { ("\nError! Memory not allocated\n"); printfreturn 0; } // Prompt user for array elements ("\nEnter elements of array: \n"); printffor(int i = 0; i < n; i++) { ("%d", ptr+i); scanf} // Printing the array elements ("\nThe elements of the array are: "); printffor(int i = 0; i < n; i++) { ("%d ",ptr[i]); // ptr[i] is same as *(ptr + i) printf} // Deallocate the block of memory (ptr); free// Print newline and return (""); putsreturn 0; }
- Note: As
malloc()
returns a void pointer,ptr = malloc(n*sizeof(int));
automatically promotes it to anint
pointer.
- In older versions of C we might need to cast it with
ptr = (int *) malloc(n*sizeof(int));
Pointer to a Pointer: Declared with two *
symbols.
Example: A pointer to a pointer
int main() { int a = 10; int *p1 = &a; int **p2 = &p1; ("&a : Ox%u\n", &a); printf("&p1: Ox%u\n", &p1); printf(" - *p1: %d\n", *p1); printf("&p2: Ox%u\n", &p2); printf(" - *p2 : %u (garbage)\n", *p2); printf(" - **p2: %d\n", **p2); printfreturn 0; }
Example Output:
&a : Ox278518276 &p1: Ox278518280 - *p1: 10 &p2: Ox278518288 - *p2 : 278518276 (garbage) - **p2: 10
A multidimensional array can be thought of as an array of arrays.
Example: Creating a 2D array (
**array
) dynamically without bracket notion.#include <stdio.h> #include <stdlib.h> int main() { int **array; int row, col; ("Give me rows and columns: \n"); printf("%d%d", &row, &col); scanf// Allocate memory for the 1D array. // - Note how we are doing sizeof(int *), not sizeof(int)! = malloc(row * sizeof(int *)); array if (array == NULL) { ("out of memory\n"); printf(1); exit} // Allocate memory for the rest of the 2D array. for (int i = 0; i < row; i++) { *(array+i) = malloc(col * sizeof(int)); if(array[i] == NULL) { ("out of memory\n"); printf(1); exit} } // Assign values and print contents of array for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { *(*(array+i)+j) = i; // ^ Same thing as array[i][j] = i; ("%d \t", *(*(array+i)+j)); printf} ("\n"); printf} // Deallocate the array and exit for (int i = 0; i < row; i++) { (*(array+i)); free} (array); free= NULL; array return 0; }
Instructions: Read each piece of code and determine the output of each numbered section.
- (Code with answers is provided below the uncommented code)
Question: Pointer Arithmetic
#include <stdio.h> int main() { int *p; int sample[3] = { -1, 6, 5 }; // I. = sample; p ("%d\n", *p); printf // II. *p = *(p)*3; ("%d\n", *p); printf // III. = ++p; p ("%d\n", *p); printf // IV. = p++; p ("%d\n", *p); printf // V. *p = *(p - 1); ("%d\n", *p); printf // VI. ++(*p); ("%d\n", *p); printf}
#include <stdio.h> int main() { int *p; int sample[3] = { -1, 6, 5 }; // I. Prints "-1" = sample; p ("%d\n", *p); printf // II. Prints "-3" (-1 x 3) *p = *(p)*3; ("%d\n", *p); printf // III. Prints "6" (pre-incremented returns x+1) = ++p; p ("%d\n", *p); printf // IV. Prints "6" (post-incremented returns x) = p++; p ("%d\n", *p); printf // V. Prints "-3" *p = *(p - 1); ("%d\n", *p); printf // VI. Prints "-2" (-3 + 1) ++(*p); ("%d\n", *p); printf}
Question: Pointer Confusion
#include <stdio.h> #include <stdlib.h> int main() { int *x, *y, *z, *a, b[3] = {-4, 5, -6}; = malloc(3 * sizeof(int)); a = a; x for (int k = 1; k < 4; k++) [k - 1] = k; a// I. ("%d\t%d\t%d\n", a[0], a[1], a[2]); printf = &b[2]; z = (++x) + 1; y *x = *x + 4; // II. ("%d\t%d\t%d\n", *x, *y, *z); printf *(--z) = *(y - 1) + *x; *(z + 1) = *(x + 1) - 3; // III. ("%d\n", *z); printf *y-- = (*++z) - (*&a[2]); // IV. ("%d\n", *y); printf // V. ("%d\n", *x + 2); printf for (int j = 0; j < 3; j++) { // VII. ("%d\t%d\n", a[j], b[j]); printf} (a); free= NULL; a return 0; }
#include <stdio.h> #include <stdlib.h> int main() { int *x, *y, *z, *a, b[3] = {-4, 5, -6}; = malloc(3 * sizeof(int)); a = a; x for (int k = 1; k < 4; k++) [k - 1] = k; a// I. 1 2 3 ("%d\t%d\t%d\n", a[0], a[1], a[2]); printf = &b[2]; z = (++x) + 1; y *x = *x + 4; // II. 6 3 -6 ("%d\t%d\t%d\n", *x, *y, *z); printf *(--z) = *(y - 1) + *x; *(z + 1) = *(x + 1) - 3; // III. 12 ("%d\n", *z); printf *y-- = (*++z) - (*&a[2]); // IV. 6 ("%d\n", *y); printf // V. 8 ("%d\n", *x + 2); printf for (int j = 0; j < 3; j++) { // VII. 1 -4 // 6 12 // -3 0 ("%d\t%d\n", a[j], b[j]); printf} (a); free= NULL; a return 0; }
void *malloc(size_t size);
Example
malloc
:int *x = malloc(100);
void *calloc(size_t nmemb, size_t size);
malloc()
Example
calloc
:int *x = calloc(0, sizeof(int));
void free(void *_Nullable ptr);
Example
free
:free(x);
void *realloc(void *_Nullable ptr, size_t size);
void *reallocarray(void *_Nullable ptr, size_t nmemb, size_t size);
relloc
will attempt to assign a new block of memory and copy the old block contents.Example:
realloc
#include <stdio.h> #include <stdlib.h> int main () { char *str; = (char *) malloc(15); str (str, "Hello, How are"); strcpy("String = %s, Address = %p\n", str, str); printf = realloc(str, 20); str (str, " you?"); strcat("String = %s, Address = %p\n", str, str); printf (str); freereturn(0); }