Skip to content
Laviyx Learn

Try

C Interview Questions

Frequently asked C interview questions on pointers, memory, strings, structs, the preprocessor, undefined behavior and embedded C, with hints, full answers and the reasoning interviewers look for.

18 questions · Updated

  1. 1.What are the stages of compiling a C program?

    BeginnerConceptToolchain
    Show hint

    Think about what happens to #include lines, and what finally joins your code with printf.

    Show solution
    1. Preprocessing expands #include, #define and #if (see it with gcc -E).
    2. Compilation translates the C code to assembly (gcc -S).
    3. Assembly produces an object file of machine code (gcc -c).
    4. Linking combines object files and libraries into an executable.

    A syntax mistake is a compiler error; calling a function that is declared but never defined is a linker error (undefined reference).

  2. 2.Does C support pass by reference?

    BeginnerConceptFunctions
    Show hint

    What exactly does a function receive when you call it with a variable?

    Show solution

    No. C always passes arguments by value: the function receives a copy. You get the effect of pass by reference by passing a pointer:

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

    The pointer itself is still passed by value; the function changes what it points to.

  3. 3.How are strings represented in C, and what is the difference between strlen and sizeof?

    BeginnerConceptStrings
    Show hint

    How does printf("%s") know where the text ends?

    Show solution

    A string is an array of char ending with the null character '\0'. strlen counts the characters before the '\0'; sizeof on an array gives its total size in bytes, including the terminator and any unused space:

    C
    char s[16] = "hello";
    printf("%zu %zu\n", strlen(s), sizeof s);
    Output
    5 16

    On a char * pointer, sizeof gives the size of the pointer, not the string.

  4. 4.Why can't a function find the length of an array passed to it?

    BeginnerConceptPointers
    Show hint

    What type does an array parameter really have?

    Show solution

    When an array is passed to a function, it decays to a pointer to its first element. Inside the function, sizeof gives the size of the pointer, and no length information remains. Pass the length as a separate parameter:

    C
    int sum(const int *a, size_t n);   /* the usual C pattern */

    In the function that declares the array, sizeof arr / sizeof arr[0] still works.

  5. 5.What are null, wild and dangling pointers?

    IntermediateConceptPointers
    Show hint

    One is deliberate, one was never set, and one used to be valid.

    Show solution
    • Null pointer: deliberately points to nothing (NULL). Check for it before dereferencing.
    • Wild pointer: declared but never initialised, so it holds a random address.
    • Dangling pointer: points to memory that is no longer valid, after free or after the function owning a local variable has returned.

    Dereferencing any of them is undefined behavior. Initialise every pointer and set pointers to NULL after free.

  6. 6.Compare malloc, calloc and realloc.

    IntermediateConceptMemory
    Show hint

    Which one zeroes the memory? What happens to the old block when realloc fails?

    Show solution
    • malloc(bytes) allocates uninitialised memory.
    • calloc(count, size) allocates count * size bytes, all set to zero, and checks the multiplication for overflow.
    • realloc(ptr, bytes) resizes a block, moving it if needed and keeping the old contents.

    All return NULL on failure. If realloc fails, the original block is still allocated, so never write p = realloc(p, n); use a temporary:

    C
    int *tmp = realloc(p, new_size);
    if (tmp == NULL) { /* p is still valid: handle the error */ }
    else p = tmp;
  7. 7.What is a memory leak? How would you find one?

    IntermediateConceptMemory
    Show hint

    What happens when the last pointer to an allocated block goes away?

    Show solution

    A leak is heap memory that is never freed after the program loses every pointer to it. In long-running programs, leaks grow until memory runs out.

    Prevent leaks by freeing on every path (a goto cleanup block helps) and by making ownership clear. Find them with Valgrind (valgrind --leak-check=full ./app) or AddressSanitizer (gcc -fsanitize=address), which report each leaked block and where it was allocated.

  8. 8.What is the difference between a struct and a union?

    IntermediateConceptStructures
    Show hint

    Do the members get separate memory or share it?

    Show solution

    Struct members each have their own storage, so a struct is at least as big as all its members together (plus padding). Union members share one block of storage, so a union is as big as its largest member and only one member holds a meaningful value at a time.

    C
    struct S { int i; double d; };
    union U { int i; double d; };
    printf("%zu %zu\n", sizeof(struct S), sizeof(union U));
    Output
    16 8

    Unions are typically paired with an enum "tag" that records which member is active.

  9. 9.What are the different meanings of static in C?

    IntermediateConceptStorage classes
    Show hint

    It depends on whether the declaration is inside or outside a function.

    Show solution
    • Inside a function: the variable has static storage duration. It is initialised once (to zero by default) and keeps its value between calls.
    • Outside functions (on a global variable or a function): internal linkage. The name is visible only inside that .c file.
    C
    #include <stdio.h>
    
    int next_id(void) {
        static int id = 0;
        return ++id;
    }
    
    int main(void) {
        next_id();
        next_id();
        printf("%d\n", next_id());
        return 0;
    }
    Output
    3
  10. 10.What is the difference between const int *p and int *const p?

    IntermediateConceptPointers
    Show hint

    Read the declaration from right to left.

    Show solution
    • const int *p: pointer to a constant int. You cannot change *p, but you can make p point elsewhere.
    • int *const p: constant pointer to an int. You can change *p, but p always points to the same place.
    • const int *const p: neither can change.

    Mark pointer parameters const when a function only reads the data, as strlen(const char *s) does.

  11. 11.What is wrong with

    IntermediateOutput predictionPreprocessor
    Show hint

    Expand SQUARE(2 + 3) by hand, as plain text.

    Show solution

    Macros substitute text, so SQUARE(2 + 3) becomes 2 + 3 * 2 + 3, which is 11, not 25:

    C
    #include <stdio.h>
    #define SQUARE(x) x * x
    #define SQUARE_OK(x) ((x) * (x))
    
    int main(void) {
        printf("%d %d\n", SQUARE(2 + 3), SQUARE_OK(2 + 3));
        return 0;
    }
    Output
    11 25

    Parenthesise every parameter and the whole body. Even then, SQUARE_OK(i++) evaluates i++ twice, so prefer a static inline function.

  12. 12.What is undefined behavior? Give examples.

    AdvancedConceptUndefined behavior
    Show hint

    What does the C standard require of a program that overflows a signed int?

    Show solution

    Undefined behavior (UB) is code for which the C standard sets no requirements: it may crash, appear to work, or produce different results at different optimisation levels. Examples:

    • signed integer overflow (INT_MAX + 1);
    • reading or writing outside an array;
    • dereferencing NULL or a freed pointer;
    • reading an uninitialised variable;
    • modifying a variable twice without sequencing, as in i = i++ + 1.

    Compilers assume UB never happens and optimise accordingly, which can delete checks written incorrectly. Use -Wall -Wextra and -fsanitize=undefined,address to catch it.

  13. 13.What does volatile mean, and where is it used?

    AdvancedConceptEmbedded C
    Show hint

    What might an optimising compiler do with a loop that reads the same variable over and over?

    Show solution

    volatile tells the compiler that a variable may change outside the program's visible control flow, so every access must actually be performed and not cached in a register or removed. It is used for:

    • memory-mapped hardware registers;
    • variables changed by interrupt service routines;
    • volatile sig_atomic_t flags set in signal handlers.

    It does not provide atomicity or thread synchronisation; use <stdatomic.h> or locks for threads.

  14. 14.How can you check whether a machine is little-endian or big-endian?

    AdvancedCodingEmbedded C
    Show hint

    Look at the first byte in memory of a multi-byte integer through an unsigned char *.

    Show solution

    Store a known multi-byte value and inspect its lowest-addressed byte:

    C
    #include <stdint.h>
    #include <stdio.h>
    
    int main(void) {
        uint32_t x = 1;
        unsigned char first = *(unsigned char *)&x;
        printf("%s-endian\n", first == 1 ? "little" : "big");
        return 0;
    }
    Output
    little-endian

    (Output from an x86-64 machine.) Little-endian stores the least significant byte first. Network protocols use big-endian, with htonl and ntohl converting.

  15. 15.Write expressions to set, clear, toggle and test bit n of an integer.

    IntermediateCodingBit manipulation
    Show hint

    Build a mask with a single bit set using a shift.

    Show solution

    With an unsigned integer x and mask 1u << n:

    C
    unsigned x = 0x10;
    x |= 1u << 0;               /* set bit 0 */
    x &= ~(1u << 4);            /* clear bit 4 */
    x ^= 1u << 7;               /* toggle bit 7 */
    int bit7 = (x >> 7) & 1u;   /* test bit 7 */
    printf("0x%02X %d\n", x, bit7);
    Output
    0x81 1

    Use unsigned types: shifting into the sign bit of a signed integer is undefined.

  16. 16.Reverse a singly linked list in place.

    IntermediateCodingData structures
    Show hint

    You need three pointers, for the previous node, the current node and the next node.

    Show solution

    Walk the list once, turning each next pointer back towards the previous node. O(n) time, O(1) extra space:

    C
    typedef struct Node { int v; struct Node *next; } Node;
    
    Node *reverse(Node *head) {
        Node *prev = NULL;
        while (head != NULL) {
            Node *next = head->next;   /* save before overwriting */
            head->next = prev;
            prev = head;
            head = next;
        }
        return prev;                   /* the new head */
    }

    See Linked Lists for a complete program.

  17. 17.Why is gets unsafe, and what should you use instead?

    BeginnerDebuggingSecurity
    Show hint

    How does gets know how big your buffer is?

    Show solution

    gets cannot know the size of the buffer, so any input longer than the buffer overflows it, a classic security vulnerability. It was removed from the language in C11. Use fgets, which takes the size, and remove the newline it keeps:

    C
    char name[32];
    if (fgets(name, sizeof name, stdin) != NULL) {
        name[strcspn(name, "\n")] = '\0';
    }
  18. 18.What does printf("%d %d", i++, i++) print?

    AdvancedOutput predictionUndefined behavior
    Show hint

    Is the order in which function arguments are evaluated fixed?

    Show solution

    There is no correct prediction. Modifying i twice in one expression without a sequence point between the modifications is undefined behavior, and the order of argument evaluation is unspecified in any case. Different compilers, and different optimisation levels, may print different results.

    The answer interviewers want: name it as undefined behavior and rewrite it with separate statements.

Review the lessons