Interview Questions
A curated set of C interview questions that come up frequently, with concise, accurate answers. These cover memory management, pointers, scope/storage, and the language quirks interviewers most often probe.
1. What is the difference between malloc() and calloc()?
malloc(size) takes a single byte count and leaves the memory uninitialized (garbage contents). calloc(count, size) takes an element count and element size, always zero-initializes the memory, and checks the count * size multiplication for overflow internally.2. What is the difference between an array and a pointer?
sizeof(array) gives the whole block's size. A pointer is a separate variable that holds an address; sizeof(pointer) always gives the pointer's own size. Arrays decay to a pointer to their first element in most expressions, which is why they often seem interchangeable but are not the same thing.3. What is undefined behavior? Give an example.
INT_MAX + 1, is undefined behavior in C (unlike unsigned overflow, which is defined to wrap around).4. What is the difference between `const int *p` and `int *const p`?
const int *p is a pointer to a constant int — you cannot modify *p, but you can reassign p to point elsewhere. int *const p is a constant pointer to a (mutable) int — you can modify *p, but p itself cannot be reassigned once initialized.5. What is a dangling pointer?
A pointer that still holds the address of memory that has already been freed (or gone out of scope, for a stack variable). Dereferencing it is undefined behavior — the memory may have been reused for something else entirely by the time you read or write through it.
6. Explain pass by value vs pass by reference in C.
7. What does static mean for a local variable vs a global variable?
static makes it retain its value between function calls instead of being re-initialized on every call — it still has function-local scope, but file/program-level lifetime. For a global variable or function, static gives it internal linkage, restricting visibility to the current translation unit (file) only.8. What is a memory leak, and how do you prevent it?
malloc()/calloc()/realloc() is never freed, and every pointer to it is lost, so the program can no longer free or reuse it. Prevent it by matching every successful allocation with exactly one free(), tracking ownership clearly, and using tools like Valgrind or AddressSanitizer to catch leaks during testing.9. Explain the stack vs the heap.
malloc() and friends) that persists until explicitly freed, is larger, but slower to allocate and requires manual management.10. What is the difference between struct and union?
struct allocates separate memory for each member, so all members exist simultaneously and sizeof(struct) is at least the sum of its members (plus padding). A union overlaps all members in the same memory, so only one member holds a valid value at a time, and sizeof(union) equals the size of its largest member.11. What happens if you forget to free() allocated memory?
The memory remains reserved for the process until it exits — this is a memory leak. In a long-running program (a server, a daemon) repeated leaks accumulate and can eventually exhaust available memory, degrading performance or crashing the process.
12. What is the difference between ++i and i++?
i by one, but ++i (pre-increment) evaluates to the new, already-incremented value, while i++ (post-increment) evaluates to the original value before incrementing. This only matters when the expression result is used, e.g. arr[i++] vs arr[++i].13. What is a NULL pointer, and how is it different from an uninitialized pointer?
NULL pointer is explicitly set to a well-defined "points to nothing" value, and checking if (p == NULL) is safe and meaningful. An uninitialized pointer holds an indeterminate, garbage address — it is not guaranteed to be NULL, so checking it against NULL tells you nothing, and dereferencing it is undefined behavior.14. What does the volatile keyword do?
It tells the compiler a variable's value can change outside the normal flow of the program (hardware, a signal handler, another thread), preventing the compiler from optimizing away or reordering reads/writes to it. It does not provide atomicity or thread-safety by itself.
15. What is the difference between #define and const?
#define is a preprocessor text substitution with no type and no scope — it is replaced before compilation even begins, so the compiler and debugger never see the name. const creates an actual typed variable that participates in scoping and type checking, and is visible to the debugger.16. What is a segmentation fault, and what commonly causes it?
NULL or dangling pointer, writing past the end of an array, or a stack overflow from deep/unbounded recursion.17. Why should you avoid using gets()?
gets() reads a line from input with no way to limit how many bytes it writes, so any input longer than the destination buffer overflows it. It was considered so dangerous that it was removed entirely from the C11 standard. Use fgets(), which takes an explicit buffer size, instead.18. What is the difference between a shallow copy and a deep copy of a struct with a pointer member?
a = b;) copies each member's value, including any pointer members — this is a shallow copy: both structs now point to the same heap memory. A deep copy additionally allocates new memory and copies the pointed-to data itself, so each struct owns an independent copy.struct buffer {
char *data;
size_t len;
};
// Shallow copy: dst.data and src.data point to the SAME memory.
struct buffer shallow_copy(struct buffer src) {
return src; // struct assignment copies the pointer value only
}
// Deep copy: dst.data points to independently allocated, copied memory.
struct buffer deep_copy(struct buffer src) {
struct buffer dst;
dst.len = src.len;
dst.data = malloc(src.len);
if (dst.data != NULL) {
memcpy(dst.data, src.data, src.len);
}
return dst;
}19. What is the purpose of a header guard?
#ifndef/#define/#endif, or #pragma once) prevents a header file's contents from being processed more than once per translation unit. Without one, including the same header twice (directly or transitively) causes duplicate declaration errors.20. What is the difference between a compiler warning and a compiler error?
-Wall -Wextra (and often -Werror in CI) is considered essential practice.