C Interview Questions and Answers

These are the C questions you'll encounter in technical interviews, each with a detailed written answer. Master pointers and memory management, then work through advanced topics like function pointers and the preprocessor.

40 questions with answersLast updated: Oct 10, 2026
Start a mock interview

What is C?

C is a procedural, low-level language that remains foundational to computer science. Its simplicity and efficiency make it ideal for operating systems, embedded systems, and performance-critical applications.

C interviews assess your understanding of pointers, memory management, the preprocessor, and how to write efficient, portable code. You'll discuss memory layouts, function pointers, and low-level programming concepts.

C expertise is invaluable for embedded systems and systems programming roles. Master the language and you'll understand how computers really work.

Reading answers is not the same as giving them. Sit a full mock interview and get scored on how you actually explain them.

Try a mock interview

C Interview Questions and Answers

1Multiple choice

How would you characterize C as a programming language and its primary design philosophy?

Answer

C is a procedural language designed for system-level programming, offering direct memory access through pointers and minimal runtime overhead.

2Multiple choice

What are the key benefits that make C suitable for systems programming and embedded development?

Answer

C's efficiency, minimal overhead, and direct hardware access make it ideal for operating systems, embedded systems, and performance-critical applications.

3Multiple choice

Explain what a pointer is and how it stores memory addresses in C

Answer

Pointers store memory addresses. The & operator gets an address; the * operator dereferences it to access the value at that address.

4Multiple choice

How do declaration and definition differ when defining variables and functions in C?

Answer

Declaration announces a variable/function exists and its type; definition allocates storage or provides implementation. One declaration can have multiple definitions.

5Multiple choice

What characteristics does a static variable have regarding scope and lifetime?

Answer

Static variables have file or local scope, persist throughout program execution, and retain their value across function calls.

6Multiple choice

How does typedef allow you to create aliases for existing data types?

Answer

typedef creates a new name for an existing type. Example: typedef unsigned int uint32_t makes uint32_t an alias for unsigned int.

7Multiple choice

Explain how structures enable grouping related data of different types together

Answer

Structures use struct keyword to group mixed data types. Members are accessed via dot notation (var.member) or arrow notation (ptr->member).

8Multiple choice

How does dynamic memory allocation allow runtime memory requests in C?

Answer

malloc and calloc allocate memory on the heap at runtime. This memory must be freed with free() to avoid leaks.

9Multiple choice

What are the differences between malloc and calloc in terms of initialization and usage?

Answer

malloc(size) returns uninitialized memory. calloc(num, size) returns zero-initialized memory suitable for arrays.

10Multiple choice

What role do preprocessor directives like #include and #define play before compilation?

Answer

The preprocessor processes directives before compilation: #include includes files, #define creates macros, #ifdef handles conditional compilation.

11Written answer

Describe C's characteristics as a low-level, procedural language and its design goals for system programming

Answer

C is a procedural language designed for efficiency and direct hardware control. Its design goals include minimal runtime overhead, direct memory access through pointers, and portability across platforms. C lacks high-level abstractions like automatic memory management or garbage collection, placing responsibility on the programmer. This makes C suitable for operating systems, embedded systems, and performance-critical applications where control and efficiency are paramount. The language provides low-level operations while maintaining enough abstraction to be portable across different hardware platforms.

12Written answer

Explain pointer mechanics including declaration, dereferencing, and pointer arithmetic

Answer

A pointer declaration reserves space for a memory address: int *ptr declares ptr as a pointer to int. The & operator gets an address: int x; ptr = &x; makes ptr point to x. The * operator dereferences: *ptr accesses the value at the address. Pointer arithmetic treats pointers as arrays: ptr++ moves to the next element based on the type size. Accessing arrays through pointers: *(ptr + i) accesses the i-th element. Understanding pointer mechanics is crucial for array/string manipulation and dynamic memory allocation.

13Written answer

Describe how malloc, calloc, and free manage memory at runtime and common pitfalls

Answer

malloc(size) allocates size bytes and returns a void pointer; the programmer must cast it. calloc(num, size) allocates space for num elements of size bytes, initializing all bytes to zero. free(ptr) deallocates memory. Common pitfalls include: (1) not checking if allocation succeeded before using the pointer, (2) forgetting to free memory, causing leaks, (3) using freed memory (dangling pointers), (4) freeing the same pointer twice, (5) allocating the wrong size. Double-checking allocation and proper cleanup in all code paths prevents these issues.

14Written answer

Explain how structures organize heterogeneous data and how to access structure members

Answer

Structures group different data types: struct Point { int x; int y; } defines a structure with two integers. Members are accessed via dot notation for variables: p.x and via arrow notation for pointers: ptr->x (equivalent to (*ptr).x). Memory layout is contiguous with potential padding for alignment. Defining typedef struct simplifies usage. Nested structures are possible. Structures form the foundation for building complex data types and are essential for organizing related data in systems programming.

15Written answer

Describe arrays, multi-dimensional arrays, and the relationship between arrays and pointers

Answer

Arrays are contiguous memory blocks: int arr[10] allocates space for 10 integers. Multi-dimensional arrays are matrices: int matrix[3][4] creates a 3x4 array. Arrays decay to pointers in most contexts: int *ptr = arr makes ptr point to arr[0]. Pointer arithmetic traverses arrays: arr[i] is equivalent to *(arr + i). Multi-dimensional arrays use pointer-to-array types: int (*ptr)[4] points to an array of 4 integers. Understanding array-pointer equivalence is fundamental to C.

16Written answer

Contrast pass-by-value with pass-by-reference using pointers and their implications

Answer

C uses pass-by-value for all parameters: values are copied into function parameters. To simulate pass-by-reference, pass pointers: void modify(int *x) { *x = 5; } modifies the original variable. For arrays and structures, copying is inefficient, so they're often passed by pointer. Pass-by-value protects the original variable from accidental modification; pass-by-pointer allows intentional modification. Choosing between them depends on whether the function should modify the argument and efficiency concerns.

17Written answer

Explain variable scope (local, global, static) and their visibility and lifetime

Answer

Local variables are declared inside functions, visible only within that scope, and exist for the function's duration. Global variables are declared outside functions, visible everywhere (within the same or linked files), and exist for the program's lifetime. Static variables declared inside functions retain their value between calls and are initialized once. Static global variables are visible only in their file. External variables allow visibility across files. Proper scoping prevents naming conflicts and clarifies code intent. Global state makes debugging harder; prefer local scope.

18Written answer

Describe how to read from and write to files, and the importance of closing file handles

Answer

File operations use FILE pointers: FILE *fp = fopen(filename, mode) opens a file. fopen returns NULL on failure, so always check. Reading uses fgets for strings, fscanf for formatted input, fread for binary data. Writing uses fputs, fprintf, fwrite. Always close files with fclose(fp) to flush buffers and release resources. Unclosed files cause resource leaks and data loss if not flushed. Using fopen/fclose ensures proper resource management. Modern practice uses error checking after every file operation.

19Written answer

Explain how macros, conditional compilation, and includes work during preprocessing

Answer

#define creates macros: #define MAX 100 replaces MAX with 100 throughout. Function-like macros: #define ADD(a,b) ((a)+(b)) use parameters. #include tells the preprocessor to include a file: #include <stdio.h> for system headers, #include "custom.h" for local files. #ifdef, #if, #ifndef enable conditional compilation, including/excluding code based on conditions. Preprocessor runs before compilation, expanding macros and including files. Debugging macros is tricky since errors appear in expanded code, not the macro definition.

20Written answer

Discuss why manual memory management requires careful attention to avoid leaks and corruption

Answer

C requires explicit memory allocation and deallocation. Failing to free allocated memory causes leaks where memory becomes inaccessible but not reused. Accessing freed memory (use-after-free) causes undefined behavior and crashes. Overwriting allocated memory (buffer overflow) corrupts the heap and adjacent data. Double-freeing the same pointer is undefined behavior. These issues are difficult to debug because errors appear distant from their cause. Best practices include: always check allocation success, write cleanup code immediately after allocation, use consistent allocation/deallocation patterns, and validate buffer sizes before writing.

21Spoken answer

Walk through how you would debug a segmentation fault in a C program and identify the root cause

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I'd first enable core dumps to get a stack trace. I'd use gdb to run the program and identify which line caused the fault. Common causes include dereferencing NULL pointers, accessing freed memory (use-after-free), or writing outside allocated buffers. I'd add debug prints or use gdb breakpoints to inspect pointer values and memory state. I'd verify all pointers are properly initialized before use and check array bounds.

22Spoken answer

Describe a situation where you used dynamic memory allocation and how you ensured proper cleanup

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I allocated a dynamic array with malloc, used it for calculations, and ensured free() was called in all code paths including error handling. I checked that malloc succeeded before using the pointer. I avoided double-free by setting pointers to NULL after freeing. I used consistent allocation/deallocation patterns throughout the codebase.

23Spoken answer

Explain how you would implement a linked list data structure from scratch in C

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I defined a struct node with data and a pointer to the next node. I implemented functions to create, insert at head/tail, search, delete, and print the list. Each function handled memory carefully, checking pointers and properly freeing nodes. Insertions allocated memory; deletions freed it. I wrote a main function to test the operations.

24Spoken answer

Talk about a time you optimized C code for performance and what techniques you applied

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I profiled the code using gprof to identify hot spots. I replaced slow string operations with optimized versions, avoided repeated calculations by caching results, and reduced memory allocations in tight loops. I used efficient algorithms like sorting before searching. I compiled with optimization flags (-O2, -O3) and reviewed generated assembly to understand the performance.

25Spoken answer

Describe how you would read structured data from a binary file and parse it correctly

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I read the file in binary mode and cast the data to the appropriate struct. I was careful with endianness and structure packing. I checked file operations for errors and read only the expected number of bytes. I validated the data before using it. I used #pragma pack or compiler flags to control structure padding to match file format expectations.

26Spoken answer

Explain how you would handle errors when file operations fail in a production system

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I checked the return values of all file operations: fopen returns NULL on failure, fread returns the number of items read, fclose can fail writing buffered data. When operations failed, I printed error messages using perror() or strerror(), freed allocated resources, and returned error codes. I logged details for debugging while providing user-friendly error messages.

27Spoken answer

Walk through how you would pass data structures safely between functions using pointers

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I used const pointers when functions shouldn't modify data, passed large structures by pointer to avoid copying, and validated pointers before dereferencing. I documented which function owns pointer memory and which must free it. I avoided pointer aliasing issues by not assuming multiple pointers refer to the same location.

28Spoken answer

Describe how you would implement a generic sorting function using function pointers

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I used qsort from the standard library, which takes a function pointer for comparison. I defined a comparison function matching qsort's requirements: taking two const void pointers, comparing them, and returning -1, 0, or 1. This made the sort algorithm reusable for any data type. I explained how the callback pattern enables generic code in C.

29Spoken answer

Talk about memory alignment and padding in structures and why it matters

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I showed how the compiler pads structures to align members on word boundaries for efficient hardware access. Example: struct { char c; int i; } wastes space between c and i. Using #pragma pack(1) eliminates padding but sacrifices performance. I demonstrated how to inspect sizeof() and offsetof() to understand memory layout.

30Spoken answer

Explain how you would debug a memory leak using tools like valgrind

This browser cannot record audio. Answer the question out loud anyway, then compare yourself against the model answer below.

Answer

I used valgrind --leak-check=full to analyze the program and identify which memory allocations weren't freed. I used gdb to set breakpoints on malloc and free to trace allocation history. I added instrumentation to malloc/free calls to log all allocations and verify they were freed. Once leaks were identified, I traced back to the code causing them.

31Coding

Write a function that reverses a string in-place without using library functions

#include <string.h>

void reverse_string(char *str) {
    // Implement string reversal
}

Answer

#include <string.h>

void reverse_string(char *str) {
    int left = 0;
    int right = strlen(str) - 1;
    while (left < right) {
        char temp = str[left];
        str[left] = str[right];
        str[right] = temp;
        left++;
        right--;
    }
}
32Coding

Allocate a 2D array dynamically and implement functions to set and get values

#include <stdlib.h>

int** allocate_matrix(int rows, int cols) {
    // Allocate matrix
}

void free_matrix(int **matrix, int rows) {
    // Free allocated memory
}

Answer

#include <stdlib.h>

int** allocate_matrix(int rows, int cols) {
    int **matrix = malloc(rows * sizeof(int*));
    if (!matrix) return NULL;
    for (int i = 0; i < rows; i++) {
        matrix[i] = malloc(cols * sizeof(int));
        if (!matrix[i]) return NULL;
    }
    return matrix;
}

void free_matrix(int **matrix, int rows) {
    for (int i = 0; i < rows; i++) {
        free(matrix[i]);
    }
    free(matrix);
}
33Coding

Write a program that reads a file and counts the number of lines

#include <stdio.h>

int count_lines(const char *filename) {
    // Count lines in file
}

Answer

#include <stdio.h>

int count_lines(const char *filename) {
    FILE *fp = fopen(filename, "r");
    if (!fp) return -1;
    int count = 0;
    int ch;
    while ((ch = fgetc(fp)) != EOF) {
        if (ch == '\n') count++;
    }
    fclose(fp);
    return count;
}
34Coding

Implement array operations using pointer arithmetic instead of array indexing

#include <stdio.h>

void print_array(int *arr, int size) {
    // Print array using pointer arithmetic
}

Answer

#include <stdio.h>

void print_array(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", *(arr + i));
    }
    printf("\n");
}
35Coding

Create a Person structure with name and age, and implement copy and display functions

#include <stdio.h>
#include <string.h>

typedef struct {
    char *name;
    int age;
} Person;

Person* create_person(const char *name, int age) {
    // Create and allocate person
}

Answer

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char *name;
    int age;
} Person;

Person* create_person(const char *name, int age) {
    Person *p = malloc(sizeof(Person));
    if (!p) return NULL;
    p->name = malloc(strlen(name) + 1);
    if (!p->name) { free(p); return NULL; }
    strcpy(p->name, name);
    p->age = age;
    return p;
}

void display_person(Person *p) {
    if (p) printf("%s, %d\n", p->name, p->age);
}

void free_person(Person *p) {
    if (p) { free(p->name); free(p); }
}
36Coding

Implement a safe string copy function that avoids buffer overflow

#include <string.h>

char* safe_string_copy(const char *source, size_t max_length) {
    // Implement safe copy
}

Answer

#include <stdlib.h>
#include <string.h>

char* safe_string_copy(const char *source, size_t max_length) {
    if (!source) return NULL;
    size_t len = strlen(source) + 1;
    if (len > max_length) return NULL;
    char *dest = malloc(len);
    if (!dest) return NULL;
    strncpy(dest, source, len - 1);
    dest[len - 1] = '\0';
    return dest;
}
37Coding

Implement a comparison callback function for sorting integers

#include <stdlib.h>

int compare_integers(const void *a, const void *b) {
    // Implement comparison
}

Answer

#include <stdlib.h>

int compare_integers(const void *a, const void *b) {
    int val_a = *(int*)a;
    int val_b = *(int*)b;
    return val_a - val_b;
}
38Coding

Write a wrapper function for malloc that checks for allocation failure

#include <stdlib.h>
#include <stdio.h>

void* safe_malloc(size_t size) {
    // Allocate with error checking
}

Answer

#include <stdlib.h>
#include <stdio.h>

void* safe_malloc(size_t size) {
    void *ptr = malloc(size);
    if (!ptr) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }
    return ptr;
}
39Coding

Read binary data from a file into a structure array

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int id;
    float value;
} Record;

Record* read_records(const char *filename, int *count) {
    // Read binary records
}

Answer

#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int id;
    float value;
} Record;

Record* read_records(const char *filename, int *count) {
    FILE *fp = fopen(filename, "rb");
    if (!fp) return NULL;
    fseek(fp, 0, SEEK_END);
    size_t size = ftell(fp);
    int num_records = size / sizeof(Record);
    rewind(fp);
    Record *records = malloc(num_records * sizeof(Record));
    if (!records) { fclose(fp); return NULL; }
    fread(records, sizeof(Record), num_records, fp);
    fclose(fp);
    *count = num_records;
    return records;
}
40Coding

Create a macro that safely swaps two values without a temporary variable

#define SWAP(a, b) \
    // Implement safe swap macro

Answer

#define SWAP(a, b) do { \
    typeof(a) temp = a; \
    a = b; \
    b = temp; \
} while (0)