Skip to content
Laviyx Learn

Try

C Pointers and Memory Practice

Practise pointers, pointer arithmetic, output parameters, malloc, realloc and free, and linked lists in C.

Intermediate8 problemsUpdated

Review first: Pointers, Pointer Arithmetic, Pointers and Functions, Dynamic Memory, Linked Lists

  1. 1.Swap through pointers

    Beginner

    Write void swap(int *a, int *b) and use it to sort three variables x = 9, y = 2, z = 5 into ascending order with at most three swaps.

    Show hint

    Compare and swap like a tiny bubble sort: (x, y), then (y, z), then (x, y) again.

    Show solution
    C
    #include <stdio.h>
    
    void swap(int *a, int *b) {
        int t = *a;
        *a = *b;
        *b = t;
    }
    
    int main(void) {
        int x = 9, y = 2, z = 5;
        if (x > y) swap(&x, &y);
        if (y > z) swap(&y, &z);
        if (x > y) swap(&x, &y);
        printf("%d %d %d\n", x, y, z);
        return 0;
    }
    Output
    2 5 9
  2. 2.Several results through pointers

    Intermediate

    Write void stats(const int *a, int n, int *min, int *max, double *avg) and use it on {14, 3, 27, 8, 19}.

    Show hint

    Initialise *min and *max with a[0], then loop from index 1.

    Show solution
    C
    #include <stdio.h>
    
    void stats(const int *a, int n, int *min, int *max, double *avg) {
        int total = a[0];
        *min = *max = a[0];
        for (int i = 1; i < n; i++) {
            if (a[i] < *min) *min = a[i];
            if (a[i] > *max) *max = a[i];
            total += a[i];
        }
        *avg = (double)total / n;
    }
    
    int main(void) {
        int data[] = {14, 3, 27, 8, 19};
        int lo, hi;
        double avg;
        stats(data, 5, &lo, &hi, &avg);
        printf("min %d, max %d, avg %.1f\n", lo, hi, avg);
        return 0;
    }
    Output
    min 3, max 27, avg 14.2
  3. 3.Sum an array with pointer arithmetic

    Intermediate

    Without using [], write int sum_range(const int *begin, const int *end) that adds the elements from begin up to (but not including) end. Use it to add the middle three elements of {5, 10, 15, 20, 25}.

    Show hint

    Loop for (const int *p = begin; p < end; p++). The middle three start at a + 1 and end before a + 4.

    Show solution
    C
    #include <stdio.h>
    
    int sum_range(const int *begin, const int *end) {
        int total = 0;
        for (const int *p = begin; p < end; p++) total += *p;
        return total;
    }
    
    int main(void) {
        int a[] = {5, 10, 15, 20, 25};
        printf("%d\n", sum_range(a + 1, a + 4));
        printf("%d\n", sum_range(a, a + 5));
        return 0;
    }
    Output
    45
    75
  4. 4.Allocate an array of squares

    Intermediate

    Read n, allocate an array of n integers with malloc, fill it with the squares 1, 4, 9, ..., print them, and free the memory. Check that malloc succeeded.

    Show hint

    int *a = malloc(n * sizeof *a); then check a == NULL before using it.

    Show solution
    C
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
        int n;
        if (scanf("%d", &n) != 1 || n <= 0) return 1;
        int *a = malloc(n * sizeof *a);
        if (a == NULL) return 1;
        for (int i = 0; i < n; i++) a[i] = (i + 1) * (i + 1);
        for (int i = 0; i < n; i++) printf("%d ", a[i]);
        printf("\n");
        free(a);
        return 0;
    }
    Output
    6
    1 4 9 16 25 36
  5. 5.A growable array with realloc

    Advanced

    Read whole numbers until the input ends, storing them in an array that starts with room for 2 and doubles its capacity with realloc when full. Print how many numbers were read, the final capacity and the numbers in reverse order.

    Show hint

    Assign realloc's result to a temporary pointer, so a failure does not lose the original block. Loop while (scanf("%d", &x) == 1).

    Show solution
    C
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void) {
        int capacity = 2, count = 0, x;
        int *items = malloc(capacity * sizeof *items);
        if (items == NULL) return 1;
    
        while (scanf("%d", &x) == 1) {
            if (count == capacity) {
                int *bigger = realloc(items, 2 * capacity * sizeof *items);
                if (bigger == NULL) {
                    free(items);
                    return 1;
                }
                items = bigger;
                capacity *= 2;
            }
            items[count++] = x;
        }
    
        printf("%d numbers, capacity %d\n", count, capacity);
        for (int i = count - 1; i >= 0; i--) printf("%d ", items[i]);
        printf("\n");
        free(items);
        return 0;
    }
    Output
    4
    8
    15
    16
    23
    5 numbers, capacity 8
    23 16 15 8 4
  6. 6.Write your own strdup

    Intermediate

    Write char *my_strdup(const char *s) that returns a newly allocated copy of s (or NULL if allocation fails). Copy "heap copy", change the copy's first letter to uppercase, and print both strings.

    Show hint

    Allocate strlen(s) + 1 bytes: the extra byte is for the '\0'.

    Show solution
    C
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char *my_strdup(const char *s) {
        char *copy = malloc(strlen(s) + 1);
        if (copy == NULL) return NULL;
        strcpy(copy, s);
        return copy;
    }
    
    int main(void) {
        const char *original = "heap copy";
        char *copy = my_strdup(original);
        if (copy == NULL) return 1;
        copy[0] = 'H';
        printf("%s | %s\n", original, copy);
        free(copy);
        return 0;
    }
    Output
    heap copy | Heap copy
  7. 7.Build and sum a linked list

    Intermediate

    Read whole numbers until the input ends and append each to the end of a singly linked list. Print the list as a -> b -> NULL, then its sum, and free every node.

    Show hint

    Keep a tail pointer so appending is O(1). When freeing, save next before calling free.

    Show solution
    C
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Node {
        int value;
        struct Node *next;
    } Node;
    
    int main(void) {
        Node *head = NULL, *tail = NULL;
        int x;
        while (scanf("%d", &x) == 1) {
            Node *n = malloc(sizeof *n);
            if (n == NULL) return 1;
            n->value = x;
            n->next = NULL;
            if (tail) tail->next = n;
            else head = n;
            tail = n;
        }
    
        int sum = 0;
        for (Node *p = head; p != NULL; p = p->next) {
            printf("%d -> ", p->value);
            sum += p->value;
        }
        printf("NULL\nsum %d\n", sum);
    
        while (head != NULL) {
            Node *next = head->next;
            free(head);
            head = next;
        }
        return 0;
    }
    Output
    3
    1
    4
    1
    5
    3 -> 1 -> 4 -> 1 -> 5 -> NULL
    sum 14
  8. 8.Sort with qsort and a callback

    Advanced

    Sort {42, -3, 17, 8, -11, 25} with qsort, first ascending and then by absolute value (smallest first), printing the array after each sort.

    Show hint

    A comparison function receives const void * pointers: convert them with *(const int *)a. Return (x > y) - (x < y) to avoid overflow.

    Show solution
    C
    #include <stdio.h>
    #include <stdlib.h>
    
    int ascending(const void *a, const void *b) {
        int x = *(const int *)a, y = *(const int *)b;
        return (x > y) - (x < y);
    }
    
    int by_abs(const void *a, const void *b) {
        int x = abs(*(const int *)a), y = abs(*(const int *)b);
        return (x > y) - (x < y);
    }
    
    void print(const int *v, int n) {
        for (int i = 0; i < n; i++) printf("%d ", v[i]);
        printf("\n");
    }
    
    int main(void) {
        int v[] = {42, -3, 17, 8, -11, 25};
        qsort(v, 6, sizeof v[0], ascending);
        print(v, 6);
        qsort(v, 6, sizeof v[0], by_abs);
        print(v, 6);
        return 0;
    }
    Output
    -11 -3 8 17 25 42
    -3 8 -11 17 25 42