Menu
CoddyTech

C Pointers Interview Questions

The topic C interviews spend most time on: invalid pointers, const, function pointers and pointer arithmetic.

10 questions
  1. What is a pointer in C?

    A pointer is a variable that stores the address of another object. &x takes an address, *p reads or writes the object behind it, and the pointer's type gives *p and p + 1 the object's size.

    C
    #include <stdio.h>
    
    int main(void) {
        int x = 10;
        int *p = &x;      /* p holds the address of x */
        *p = 25;          /* write through the pointer */
        printf("x = %d, *p = %d\n", x, *p);
        printf("p points to x: %s\n", p == &x ? "yes" : "no");
        return 0;
    }

    It prints x = 25, *p = 25 and yes. More in pointers in C.

  2. What is the difference between a NULL pointer, a void pointer, a dangling pointer and a wild pointer?

    A NULL pointer points to nothing and can be tested. A void * is a generic pointer with no type; convert it before use (it can be NULL too). A dangling pointer points to freed or out-of-scope memory, and a wild one was never initialized; dereferencing either is undefined behavior. Initialize every pointer and set it to NULL after free.

  3. What is a void pointer, and why can you not dereference it?

    A void * holds the address of any object type, which is how malloc, qsort and memcpy stay generic. You cannot dereference it because the compiler does not know the size or type behind it; convert it first.

    C
    #include <stdio.h>
    
    void print_value(const void *p, char type) {
        if (type == 'i') printf("int: %d\n", *(const int *) p);
        if (type == 'd') printf("double: %.2f\n", *(const double *) p);
    }
    
    int main(void) {
        int i = 42;
        double d = 3.14159;
        print_value(&i, 'i');
        print_value(&d, 'd');
        return 0;
    }

    Arithmetic on void * is not standard C (GCC allows it with size 1), so use char * for byte offsets.

  4. Which variable does **q = 20 change when q points to p?

    C
    #include <stdio.h>
    
    int main(void) {
        int x = 10;
        int *p = &x;
        int **q = &p;
        **q = 20;
        printf("%d\n", x);
        return 0;
    }

    It prints 20. *q is p and **q is x, so **q = 20 writes to x. A function takes a pointer to a pointer when it must change the caller's pointer:

    void make_buffer(char **out, size_t n) {
        *out = malloc(n);   /* changes the caller's pointer */
    }
    
  5. What is the difference between const int *p, int *const p and const int *const p?

    const int *p points to a const int: p can move but *p cannot be written. int *const p is a const pointer: *p can be written but p cannot move. const int *const p allows neither. Read right to left; const applies to what is on its left, or its right if nothing is on its left. Use const T * for read-only parameters, as strlen does.

  6. What is the difference between *(p + 2) and *p + 2?

    C
    #include <stdio.h>
    
    int main(void) {
        int a[] = {10, 20, 30, 40};
        int *p = a;
        printf("%d %d\n", *(p + 2), *p + 2);
        return 0;
    }

    It prints 30 12. p + 2 moves two ints forward, scaled by sizeof(int), so *(p + 2) is a[2]. * binds tighter than +, so *p + 2 is a[0] + 2. See pointer arithmetic.

  7. What is a function pointer, and where is it used?

    A function pointer stores a function's address so you can call it later or pass it on, declared as return_type (*name)(params). C uses it for callbacks and dispatch tables.

    C
    #include <stdio.h>
    #include <stdlib.h>
    
    int cmp_asc(const void *a, const void *b) {
        int x = *(const int *) a, y = *(const int *) b;
        return (x > y) - (x < y);
    }
    
    int main(void) {
        int (*cmp)(const void *, const void *) = cmp_asc;
        int v[] = {5, 2, 9, 1, 7};
        qsort(v, 5, sizeof v[0], cmp);
        for (int i = 0; i < 5; i++) printf("%d ", v[i]);
        printf("\n");
        return 0;
    }

    It prints 1 2 5 7 9. The comparator avoids x - y, which overflows for large values of opposite sign. See function pointers.

  8. What is the difference between int *p[3] and int (*p)[3]?

    int *p[3] is an array of 3 pointers; int (*p)[3] is one pointer to an array of 3 ints. [] binds tighter than *, so the parentheses decide.

    C
    #include <stdio.h>
    
    int main(void) {
        int a = 1, b = 2, c = 3;
        int *arr_of_ptrs[3] = {&a, &b, &c};
    
        int grid[2][3] = {{1, 2, 3}, {4, 5, 6}};
        int (*row)[3] = grid;          /* points to grid[0] */
    
        printf("sizeof arr_of_ptrs: %zu\n", sizeof arr_of_ptrs);
        printf("sizeof row: %zu\n", sizeof row);
        printf("*arr_of_ptrs[1] = %d\n", *arr_of_ptrs[1]);
        printf("row[1][2] = %d\n", row[1][2]);   /* row + 1 skips a whole row */
        return 0;
    }

    Here the array is 24 bytes and the pointer 8. A 2D array decays to a pointer to an array, so row + 1 skips a whole row.

  9. What does the restrict keyword mean?

    restrict (C99) promises that, for the pointer's lifetime, an object it points to that is modified is accessed only through that pointer (or one derived from it). The compiler can then assume no overlap and vectorize.

    void add(int n, float *restrict out,
             const float *restrict a, const float *restrict b) {
        for (int i = 0; i < n; i++)
            out[i] = a[i] + b[i];
    }
    

    Breaking the promise is undefined behavior and is not checked. memcpy declares its parameters restrict for this reason: its buffers must not overlap. C++ has no restrict keyword.

  10. What is the difference between *p++, (*p)++ and *++p?

    Postfix ++ binds tighter than *, so *p++ is *(p++): it reads the current element, then moves the pointer. (*p)++ adds 1 to the value and leaves the pointer alone, and *++p moves the pointer first, then reads.

    C
    #include <stdio.h>
    
    int main(void) {
        int a[] = {10, 20, 30};
        int *p = a;
    
        int x = *p++;    /* reads a[0], then moves p to a[1] */
        printf("%d %d\n", x, *p);
    
        int y = (*p)++;  /* reads a[1], then adds 1 to a[1] */
        printf("%d %d\n", y, a[1]);
    
        int z = *++p;    /* moves p to a[2], then reads it */
        printf("%d\n", z);
        return 0;
    }

    It prints 10 20, 20 21 and 30. *p++ is the idiom behind copy loops such as while ((*dst++ = *src++)). See pointer arithmetic.

Coddy programming languages illustration

Learn to code with Coddy

Get started