C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
235: Common C Interview Questions on Pointers and Memory
Look, I've sat on both sides of the interview table. When an interviewer asks about pointers and memory in C, they aren't just checking if you know the syntax; they're checking if you actually understand how the computer's memory is laid out. They want to see if you're the kind of programmer who creates random segmentation faults or someone who knows exactly where every byte is going.
What is the actual difference between a string literal and a character array?
This is a classic "gotcha" question. You'll see two lines of code that look almost identical, but they behave completely differently in memory.
char *str1 = "Hello";
char str2[] = "Hello";
Here's the deal: str1 is a pointer to a string literal. That literal "Hello" is usually stored in a read-only section of the executable's data segment. If you try to do str1[0] = 'M';, your program will likely crash with a segmentation fault because you're trying to write to read-only memory. I can't tell you how many juniors have spent an hour debugging that.
str2, on the other hand, is an array. The compiler allocates space on the stack and copies "Hello" into it. You own that memory. You can change str2[0] to 'M' all day long, and it'll work perfectly. In an interview, the keyword you want to mention here is "storage duration" and "read-only memory."
How do I explain a dangling pointer and why it's dangerous?
A dangling pointer is basically a pointer that still holds a memory address, but the memory at that address has already been freed or deleted. It's like having a key to an apartment after the lease ended and the landlord changed the locks—or worse, someone else moved in.
int *ptr = malloc(sizeof(int));
*ptr = 42;
free(ptr);
// ptr is now a dangling pointer!
if (ptr != NULL) {
printf("%d", *ptr); // Undefined behavior. Big mistake.
}
The dangerous part is that ptr isn't NULL; it still contains the address. The code might actually work sometimes, which is the worst-case scenario because it creates a bug that only appears occasionally in production. My rule of thumb? Always set your pointer to NULL immediately after calling free(). It turns a silent, random crash into a predictable one.
When would I actually need a pointer to a pointer?
Double pointers (type **ptr) usually confuse people, but they're essential when you need to change the address a pointer is pointing to from inside another function. If you pass a single pointer to a function, you're passing the address by value. You can change the data at that address, but you can't make the original pointer point somewhere else.
Imagine you're writing a function to allocate a buffer for a string. If you use a single pointer, the allocation stays local to the function. You need a double pointer to "reach back" and update the pointer in the caller's scope:
void allocate_string(char **p_str) {
*p_str = malloc(100 * sizeof(char));
}
int main() {
char *my_string = NULL;
allocate_string(&my_string); // Pass the address of the pointer
strcpy(my_string, "Now this works!");
free(my_string);
return 0;
}
If you just passed my_string (a char *), the function would allocate memory, assign it to a local copy of the pointer, and then that memory would be leaked the moment the function returned. Using char ** lets you modify the original my_string variable directly.
📋 Practical Task
Fixing the Memory Leak in a Dynamic String Buffer
You've been handed a piece of code intended to update a system configuration string. However, the current implementation has a massive memory leak and a potential segmentation fault. The function update_config is supposed to free the old string and allocate a new one, but it's doing it incorrectly.
Your Task: Rewrite the update_config function using a double pointer so that the current_config pointer in main is correctly updated to the new memory location, and ensure no memory is leaked during the transition.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// BUGGY FUNCTION: This doesn't actually update the pointer in main
void update_config(char *config, const char *new_val) {
free(config);
config = malloc(strlen(new_val) + 1);
strcpy(config, new_val);
}
int main() {
char *current_config = malloc(20);
strcpy(current_config, "Version 1.0");
printf("Old: %s\n", current_config);
update_config(current_config, "Version 2.0");
// This will likely print "Version 1.0" or crash,
// and the memory allocated in update_config is leaked.
printf("New: %s\n", current_config);
free(current_config);
return 0;
}There are no comments for now.