C Programming with DSA Interview Questions for Freshers
40 questions with answers for candidates with Freshers — 26 easy, 14 medium.
What interviewers expect: freshers
Fresher interviews test C basics, pointer output questions, arrays and strings, simple linked list code and two or three DSA problems of easy to medium level. Interviewers check that you can write correct code without an IDE, handle edge cases like empty input and explain time complexity. Be ready to explain your college or training project and any embedded work clearly.
This set is weighted towards Linked Lists (8), C Basics, Data Types and Operators (7), Arrays and Strings (7), Trees and Graphs (5).
Pointers and memory Arrays and strings problems Linked lists and stacks Complexity analysis
Solved at this levelStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
✓ 3 questions free • Unlock the rest in seconds
01
A program that writes logs with fprintf loses the last lines when it crashes. Why, and how do you fix it?
stdio streams are buffered, so fprintf stores data in memory and writes it to disk only when the buffer fills, the file closes or fflush is called. A crash loses whatever is still in the buffer. Call fflush after important log lines, set line buffering with setvbuf(fp, NULL, _IOLBF, 0) or write critical messages to unbuffered stderr. For durability on disk, add fsync on POSIX systems.
02
What is a linked list and how is it different from an array?
A linked list is a chain of nodes where each node holds data and a pointer to the next node, allocated separately on the heap. Unlike an array, it grows easily and inserts or deletes in O(1) once you have the position, but it has O(n) access by index, extra memory per node for pointers and poor cache locality. Arrays win for random access and iteration speed.
03
What is the time complexity of common linked list operations?
Access or search by value is O(n). Insert or delete at the head is O(1). Insert at the tail is O(1) if you keep a tail pointer, otherwise O(n). Deleting a given node is O(1) in a doubly linked list but O(n) in a singly linked list, since you must find the previous node. Finding length is O(n) unless you store a count.
In-order visits left, node, right and gives sorted output for a BST. Pre-order visits node, left, right and is used to copy or serialise a tree. Post-order visits left, right, node and is used to delete a tree or evaluate expression trees. Level-order visits nodes level by level using a queue. The first three are depth first and use recursion or an explicit stack.
05
What is the difference between break and continue in C?
break immediately exits the nearest enclosing loop or switch statement, and execution continues after it. continue skips the rest of the current loop iteration and moves to the next one; in a for loop the update expression still runs. In nested loops both affect only the innermost loop, so a flag or goto is needed to exit outer loops early.
06
What is a binary search tree and what are its operation costs?
A binary search tree keeps every node's left subtree smaller and right subtree larger than the node. Search, insert and delete follow one path from the root, so they cost O(h), where h is the height. A balanced tree has h of about log n, but inserting sorted data creates a skewed tree with h equal to n. In-order traversal of a BST gives keys in sorted order.
07
Your linked list program crashes when deleting the last node. What do you check?
Check that the previous node's next pointer is set to NULL after freeing the last node, that the tail pointer is updated if you keep one and that you do not access the node after free. Also handle the case of a one-node list where head itself must become NULL, which requires passing a pointer to the head pointer. Run the code under AddressSanitizer to find invalid accesses.
08
What is a deque and how can it be implemented in C?
A deque, or double ended queue, supports insertion and removal at both the front and the rear in O(1). In C it is commonly implemented as a circular array with front and rear indexes that wrap using modulo, or as a doubly linked list. It is the core of the sliding window maximum algorithm and can act as both a stack and a queue.
Recursion is when a function calls itself on a smaller subproblem until reaching a base case. It expresses tree traversal, divide and conquer and backtracking naturally. Risks are stack overflow when depth is large, repeated work when subproblems overlap, like naive Fibonacci, and function call overhead. Use memoisation for overlapping subproblems and iterative versions when depth may be huge.
10
How do you explain the time complexity of your solution to an interviewer?
Situation: in a technical round I solved a tree problem but the interviewer questioned its efficiency. Task: justify the complexity clearly. Action: I explained that each node is visited once and does constant work, so time is O(n), and that recursion depth equals tree height, giving O(h) space, worst case O(n) for a skewed tree. Result: the interviewer agreed and moved to a harder follow-up.
11
Tell me about a time you chose the right data structure under pressure.
Situation: during a hackathon our C route planner was too slow to answer queries live. Task: fix it within a few hours. Action: I profiled it, found repeated linear searches of a list of stops and replaced them with a hash table keyed by stop id, plus a queue for BFS. Result: queries went from 4 seconds to 30 ms and we won second place.
12
What is the difference between a structure and a union?
In a structure each member has its own memory, so the size is at least the sum of members plus padding, and all members hold values at once. In a union all members share the same memory, so its size equals the largest member and only one member is meaningful at a time. Unions save memory and are used for variant types and in embedded protocol parsing.
13
What is a circular linked list and where is it used?
In a circular linked list the last node points back to the first, so there is no NULL end. You can start at any node and visit all nodes, and keeping only a tail pointer gives O(1) access to both ends. It is used in round-robin CPU scheduling, multiplayer turn order and circular buffers. Traversal loops must stop when they return to the starting node.
14
Why is a dummy or sentinel node useful in linked list code?
A dummy node placed before the real head removes special cases for an empty list or for inserting and deleting at the head, because every real node then has a previous node. Code for merging lists, removing elements and partitioning becomes shorter and less error prone. At the end, return dummy.next as the new head. It costs one extra node.
15
Merge two sorted linked lists into one sorted list.
Brute force checks all pairs in O(n squared). Sorting first with qsort and then using two pointers takes O(n log n) time and O(1) extra space but loses original indexes. A hash set gives O(n) time with O(n) memory; in C you would implement a simple open addressing table. Choose based on size, memory limits and whether indexes must be returned.
17
Write a function that dynamically allocates an array of n integers and fills it with squares.
Check the allocation and let the caller free it.
int *makeSquares(size_t n) {
int *arr = malloc(n * sizeof *arr);
if (arr == NULL) return NULL;
for (size_t i = 0; i < n; i++) {
arr[i] = (int)(i * i);
}
return arr;
}
// caller
int *a = makeSquares(10);
if (a) { /* use */ free(a); }
18
What is the difference between a declaration and a definition in C?
A declaration tells the compiler a name and its type, such as extern int count; or a function prototype, without allocating storage. A definition actually creates the object or provides the function body, such as int count = 0;. A variable can be declared many times but defined only once across the program, otherwise the linker reports a multiple definition error.
Track the top index and check bounds.
#define MAX 100
typedef struct { int data[MAX]; int top; } Stack;
void init(Stack *s) { s->top = -1; }
int push(Stack *s, int x) {
if (s->top == MAX - 1) return -1;
s->data[++s->top] = x;
return 0;
}
int pop(Stack *s, int *out) {
if (s->top < 0) return -1;
*out = s->data[s->top--];
return 0;
}
Returning an error code avoids undefined reads on empty stacks.
++i increments i and then yields the new value, while i++ yields the old value and then increments. As a standalone statement both have the same effect, and modern compilers generate the same code. The difference matters inside expressions: if i is 5, a = i++ sets a to 5, while a = ++i sets a to 6. Never use both on the same variable in one expression.
21
A search on a sorted array of 10 lakh elements is done with a linear loop. How would you justify changing it?
Linear search takes up to 10 lakh comparisons, while binary search needs about 20, because log base 2 of 10 lakh is roughly 20. If searches are frequent, this is a huge saving at zero memory cost. If data changes often, keeping it sorted costs inserts, so consider a balanced tree or hash table. Measure with realistic workloads before and after.
22
Merge two sorted arrays into a third sorted array.
Walk both arrays with two indexes.
void merge(const int *a, int n, const int *b, int m, int *out) {
int i = 0, j = 0, k = 0;
while (i < n && j < m)
out[k++] = (a[i] <= b[j]) ? a[i++] : b[j++];
while (i < n) out[k++] = a[i++];
while (j < m) out[k++] = b[j++];
}
Time O(n + m). Using <= keeps the merge stable.
Count transitions from space to non-space.
#include <ctype.h>
int countWords(const char *s) {
int count = 0, inWord = 0;
for (; *s; s++) {
if (isspace((unsigned char)*s)) {
inWord = 0;
} else if (!inWord) {
inWord = 1;
count++;
}
}
return count;
}
This handles multiple spaces, tabs and leading or trailing spaces correctly.
Swap characters from both ends moving inward.
void reverse(char *s) {
size_t n = strlen(s);
if (n < 2) return;
for (size_t i = 0, j = n - 1; i < j; i++, j--) {
char t = s[i];
s[i] = s[j];
s[j] = t;
}
}
Time O(n) and O(1) extra space. The string must be a modifiable array, not a literal.
25
A file opened with fopen is NULL in production but fine on your machine. How do you debug?
Always check the return value and print the reason with perror or strerror(errno), which shows errors like No such file or directory or Permission denied. Common causes are a relative path resolved from a different working directory, missing permissions for the service user, a full disk or too many open files. Use absolute or configured paths and close every file you open.
Situation: in my second year I could not solve even easy array problems in time. Task: become placement ready in six months. Action: I followed a topic-wise sheet, solved two problems daily in C, wrote down the pattern behind each one and revised mistakes every Sunday. Result: I solved over 300 problems, cleared three online coding tests and now explain complexity confidently.
Compare character by character until a difference or the end.
int my_strcmp(const char *a, const char *b) {
while (*a && *a == *b) {
a++;
b++;
}
return (unsigned char)*a - (unsigned char)*b;
}
Casting to unsigned char matches the standard behaviour for characters above 127. It returns zero if equal, negative if a sorts first and positive otherwise.
Flip each next pointer while walking the list.
typedef struct Node { int data; struct Node *next; } Node;
Node *reverse(Node *head) {
Node *prev = NULL, *cur = head;
while (cur) {
Node *next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
return prev;
}
Time O(n), space O(1). The returned prev is the new head.
29
What is the difference between greedy algorithms and dynamic programming?
A greedy algorithm makes the best local choice at each step and never revisits it, which works only when the greedy choice property holds, as in activity selection, Huffman coding and Dijkstra. Dynamic programming considers all relevant subproblem choices and combines them, so it works where greedy fails, such as 0/1 knapsack or coin change with arbitrary denominations. Greedy is faster when provably correct.
30
What are the basic data types in C and their typical sizes?
C has char (1 byte), short (usually 2), int (usually 4), long (4 on Windows, 8 on 64-bit Linux), long long (at least 8), float (4) and double (8). The standard only fixes minimum ranges, so sizes depend on the platform. Use sizeof to check and the fixed-width types from stdint.h such as int32_t and uint8_t when exact sizes matter.
C stores multidimensional arrays in row-major order: all elements of row 0, then row 1 and so on, in one contiguous block. Element a[i][j] of an array with C columns is at offset i * C + j. Traversing row by row is cache friendly and much faster than column by column for large matrices. When passing a 2D array to a function, every dimension except the first must be specified.
32
A loop that sums large numbers gives a negative result. What is happening?
The sum overflowed the range of int, and signed overflow in C is undefined behaviour, often wrapping to a negative value. Use a wider type like long long or int64_t for the accumulator, check before adding with a condition like if (sum > INT_MAX - x), or use compiler builtins such as __builtin_add_overflow. Compile with -fsanitize=undefined to catch it during testing.
33
Freeing a linked list causes a crash. What is the common mistake?
A common bug is freeing the current node and then reading current->next, which is a use-after-free. Save the next pointer first, then free the node, then move on. Also make sure no node is freed twice and that the caller's head pointer is set to NULL afterwards so it is not used again. Valgrind or AddressSanitizer points to the exact line.
34
How do you set, clear and toggle a particular bit in C?
Use bit masks with shift operators.
x |= (1u << n); // set bit n
x &= ~(1u << n); // clear bit n
x ^= (1u << n); // toggle bit n
int bit = (x >> n) & 1u; // read bit n
Use unsigned types so shifts are well defined. These operations are common in embedded code for configuring hardware registers.
35
Write a header guard and explain why it is needed.
A header guard stops a header from being included twice in one translation unit, which would cause redefinition errors.
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
int add(int a, int b);
#endif
Most compilers also support #pragma once, which is shorter but not part of the C standard.
36
A function returns the address of a local array and the caller gets wrong data. Why?
Local arrays live on the stack and are destroyed when the function returns, so the returned pointer is dangling and later calls overwrite that memory. Fix it by having the caller pass a buffer and its size, allocating with malloc and documenting that the caller must free it, or using a static buffer, which is not thread safe. Compilers warn about this with -Wreturn-local-addr.
37
Your stack implementation crashes with deep recursion converted to an explicit stack. What would you check?
Check for stack overflow of your own array: push must verify top < capacity and either fail or grow the array with realloc. Check pop on an empty stack returns an error instead of reading index -1. If using realloc, make sure no pointers into the old buffer are kept. Add asserts in debug builds and test with the largest expected input.
38
Insert a value into a binary search tree recursively in C.
Height is one plus the larger subtree height.
int height(const TNode *root) {
if (root == NULL) return 0;
int lh = height(root->left);
int rh = height(root->right);
return 1 + (lh > rh ? lh : rh);
}
This counts nodes on the longest root to leaf path; return -1 for empty trees if height is defined in edges. Time O(n).
40
What does sizeof return for a pointer and for an array?
sizeof on a pointer returns the size of the pointer itself, typically 8 bytes on a 64-bit system, regardless of what it points to. sizeof on an array declared in the same scope returns the total bytes of all elements, so sizeof arr / sizeof arr[0] gives the element count. Inside a function receiving an array parameter, sizeof returns pointer size, so pass the length separately.
Frequently asked questions
What is asked in C Programming with DSA interviews for Freshers?
Fresher interviews test C basics, pointer output questions, arrays and strings, simple linked list code and two or three DSA problems of easy to medium level. Interviewers check that you can write correct code without an IDE, handle edge cases like empty input and explain time complexity. Be ready to explain your college or training project and any embedded work clearly.
How many questions should I practise before a C Programming with DSA interview?
Work through all 40 questions here, then the company-wise sets for the employers you are targeting. Quality matters more than count: be able to explain why each answer is right.
Which topics matter most for Freshers?
Focus first on Pointers and memory, Arrays and strings problems, Linked lists and stacks, Complexity analysis.