C interview questions test pointers, memory allocation, structures, file handling, and systems programming concepts central to embedded and low-level development. Interviewers use C to check whether you understand what the machine is actually doing, from memory layout to the risks of manual memory management. This page covers 40 real C interview questions with answers across four formats: multiple choice, written answers, spoken responses, and live coding challenges, the same mix used in modern technical interviews.
Practice each question in your browser with no signup required. Answers stay hidden until you attempt the question: type, speak, or code your response first, then compare it against the model answer. Questions range from fundamentals for your first developer job to scenario-based questions for senior roles, so you can find the gaps in your knowledge before the real interview.
40 questions with answersLast updated: Oct 19, 2026
Choose a question. Pick any of the 40 questions. They mix multiple choice, written, spoken, and coding, the same mix a real interviewer uses.
Attempt your answer. Select a multiple-choice option, type your written response, record a spoken answer, or write code in the editor.
Reveal the model answer. Once you have attempted the question, the model answer unlocks so you can compare it with yours.
Move to the next question. Track how many questions you have attempted with the progress bar at the top of the page.
Take a mock interview. When you are ready, try a full mock technical interview on Plaicer with AI-driven follow-up questions.
C Interview Questions and Answers
0 of 40 attempted
1Multiple choice
How would you characterize C as a programming language and its primary design philosophy?
Attempt the question first to reveal the answer.
Answer
C is a procedural language designed for system-level programming, offering direct memory access through pointers and minimal runtime overhead.
2Written answer
Describe C's characteristics as a low-level, procedural language and its design goals for system programming
Attempt the question first to reveal the answer.
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.
3Spoken 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.
Attempt the question first to reveal the answer.
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.
4Coding
Write a function that reverses a string in-place without using library functions
#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--;
}
}
5Multiple choice
What are the key benefits that make C suitable for systems programming and embedded development?
Attempt the question first to reveal the answer.
Answer
C's efficiency, minimal overhead, and direct hardware access make it ideal for operating systems, embedded systems, and performance-critical applications.
6Written answer
Explain pointer mechanics including declaration, dereferencing, and pointer arithmetic
Attempt the question first to reveal the answer.
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.
7Spoken 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.
Attempt the question first to reveal the answer.
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.
8Coding
Allocate a 2D array dynamically and implement functions to set and get values
#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);
}
9Multiple choice
Explain what a pointer is and how it stores memory addresses in C
Attempt the question first to reveal the answer.
Answer
Pointers store memory addresses. The & operator gets an address; the * operator dereferences it to access the value at that address.
10Written answer
Describe how malloc, calloc, and free manage memory at runtime and common pitfalls
Attempt the question first to reveal the answer.
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.
11Spoken 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.
Attempt the question first to reveal the answer.
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.
12Coding
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
}
Attempt the question first to reveal the answer.
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;
}
13Multiple choice
How do declaration and definition differ when defining variables and functions in C?
Attempt the question first to reveal the answer.
Answer
Declaration announces a variable/function exists and its type; definition allocates storage or provides implementation. One declaration can have multiple definitions.
14Written answer
Explain how structures organize heterogeneous data and how to access structure members
Attempt the question first to reveal the answer.
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.
15Spoken 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.
Attempt the question first to reveal the answer.
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.
16Coding
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
}
Attempt the question first to reveal the answer.
Answer
#include <stdio.h>
void print_array(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", *(arr + i));
}
printf("\n");
}
17Multiple choice
What characteristics does a static variable have regarding scope and lifetime?
Attempt the question first to reveal the answer.
Answer
Static variables have file or local scope, persist throughout program execution, and retain their value across function calls.
18Written answer
Describe arrays, multi-dimensional arrays, and the relationship between arrays and pointers
Attempt the question first to reveal the answer.
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.
19Spoken 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.
Attempt the question first to reveal the answer.
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.
20Coding
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
}
How does typedef allow you to create aliases for existing data types?
Attempt the question first to reveal the answer.
Answer
typedef creates a new name for an existing type. Example: typedef unsigned int uint32_t makes uint32_t an alias for unsigned int.
22Written answer
Contrast pass-by-value with pass-by-reference using pointers and their implications
Attempt the question first to reveal the answer.
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.
23Spoken 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.
Attempt the question first to reveal the answer.
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.
24Coding
Implement a safe string copy function that avoids buffer overflow
#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;
}
25Multiple choice
Explain how structures enable grouping related data of different types together
Attempt the question first to reveal the answer.
Answer
Structures use struct keyword to group mixed data types. Members are accessed via dot notation (var.member) or arrow notation (ptr->member).
26Written answer
Explain variable scope (local, global, static) and their visibility and lifetime
Attempt the question first to reveal the answer.
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.
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.
Attempt the question first to reveal the answer.
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.
28Coding
Implement a comparison callback function for sorting integers
#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;
}
29Multiple choice
How does dynamic memory allocation allow runtime memory requests in C?
Attempt the question first to reveal the answer.
Answer
malloc and calloc allocate memory on the heap at runtime. This memory must be freed with free() to avoid leaks.
30Written answer
Describe how to read from and write to files, and the importance of closing file handles
Attempt the question first to reveal the answer.
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.
31Spoken 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.
Attempt the question first to reveal the answer.
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.
32Coding
Write a wrapper function for malloc that checks for allocation failure
Explain how macros, conditional compilation, and includes work during preprocessing
Attempt the question first to reveal the answer.
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.
35Spoken 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.
Attempt the question first to reveal the answer.
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.
36Coding
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
}
What role do preprocessor directives like #include and #define play before compilation?
Attempt the question first to reveal the answer.
Answer
The preprocessor processes directives before compilation: #include includes files, #define creates macros, #ifdef handles conditional compilation.
38Written answer
Discuss why manual memory management requires careful attention to avoid leaks and corruption
Attempt the question first to reveal the answer.
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.
39Spoken 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.
Attempt the question first to reveal the answer.
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.
40Coding
Create a macro that safely swaps two values without a temporary variable
#define SWAP(a, b) \
// Implement safe swap macro
Attempt the question first to reveal the answer.
Answer
#define SWAP(a, b) do { \
typeof(a) temp = a; \
a = b; \
b = temp; \
} while (0)
Topics covered
C fundamentals: design philosophy, declaration vs definition, typedef
40 real C interview questions across four formats: multiple choice (10), written answer (10), spoken answer (10), and coding (10).
Do I need to sign up to practice?
No. All 40 questions and model answers are free with no signup. You attempt each question first, and the model answer unlocks once you have engaged.
Who are these C interview questions for?
Developers preparing for C technical interviews at any level, from first job to senior engineer roles. Questions cover fundamentals through real-world scenarios.
What topics do the C questions cover?
The questions cover pointers, function pointers, arrays, and strings. They also test dynamic memory allocation, structures, and padding. Other topics include the preprocessor, file I/O, and debugging segmentation faults and memory leaks.
Can I practice coding questions in the browser?
Yes. Coding questions include starter code in an in-browser editor, so you can write your solution without installing anything.
How often are the questions updated?
The question bank is reviewed regularly and updated to reflect current C interview patterns.
Can I take a full mock interview?
Yes. Plaicer's mock technical interview walks you through a realistic 30 to 45 minute interview with AI-driven follow-up questions.
Are these questions useful for embedded systems interviews?
Yes. Topics like pointers, manual memory management, struct padding, and binary file handling come up often in embedded and firmware interviews.