1. According to the C standard, what is the effect of modifying a string literal via a pointer, such as char *str = "Hello"; str[0] = 'h';?
Answer: Undefined behavior — string literals live in read-only memory (like .rodata), and writing through a pointer to them is not allowed.
In C, string literals are stored in read-only memory segments (in typical implementations). The declaration char *str = "Hello"; makes str point at that read-only storage. Attempting str[0] = 'h'; tries to write to read-only memory:
- Per the C standard, modifying a string literal is undefined behavior (the standard doesn’t even promise the memory is writable).
- In practice, this usually manifests as a segmentation fault (
SIGSEGV).
The safe pattern is to copy the literal into writable storage first: char str[] = "Hello"; — a real array initialized from the literal, safe to modify. The interview answer: modifying a string literal through a pointer is UB — the literal sits in read-only memory, typically crashing with SIGSEGV.
Answer:
Undefined behavior — string literals live in read-only memory (like .rodata), and writing through a pointer to them is not allowed.
In C, string literals are stored in read-only memory segments (in typical implementations). The declaration char *str = "Hello"; makes str point at that read-only storage. Attempting str[0] = 'h'; tries to write to read-only memory:
- Per the C standard, modifying a string literal is undefined behavior (the standard doesn’t even promise the memory is writable).
- In practice, this usually manifests as a segmentation fault (
SIGSEGV).
The safe pattern is to copy the literal into writable storage first: char str[] = "Hello"; — a real array initialized from the literal, safe to modify. The interview answer: modifying a string literal through a pointer is UB — the literal sits in read-only memory, typically crashing with SIGSEGV.
2. What is the main danger of using gets() in C, leading to its deprecation and removal in C11?
Answer: It reads input without any buffer-length bound, enabling stack buffer overflows — it was removed in C11.
gets(buffer) reads characters until a newline, writing everything into the caller’s buffer with no size limit and no check. If input exceeds the buffer, it writes past the end — a buffer overflow that corrupts adjacent stack memory. Attackers exploit this for stack-smashing / code injection; it’s one of the most infamous unsafe functions in C history.
The standard finally removed gets entirely in C11 (deprecated in C99). The safe replacement is fgets(buffer, size, stdin), which caps input at size - 1 characters. The interview answer: unbounded reads into a fixed buffer → stack overflow vulnerabilities; use fgets instead.
Answer:
It reads input without any buffer-length bound, enabling stack buffer overflows — it was removed in C11.
gets(buffer) reads characters until a newline, writing everything into the caller’s buffer with no size limit and no check. If input exceeds the buffer, it writes past the end — a buffer overflow that corrupts adjacent stack memory. Attackers exploit this for stack-smashing / code injection; it’s one of the most infamous unsafe functions in C history.
The standard finally removed gets entirely in C11 (deprecated in C99). The safe replacement is fgets(buffer, size, stdin), which caps input at size - 1 characters. The interview answer: unbounded reads into a fixed buffer → stack overflow vulnerabilities; use fgets instead.
3. What function is used to compare two null-terminated C strings byte-by-byte?
Answer: strcmp().
strcmp(s1, s2) compares two C strings lexicographically (byte-by-byte by character value):
- Returns
0if the strings are equal. - Returns negative if
s1 < s2. - Returns positive if
s1 > s2.
if (strcmp(str, "quit") == 0) { /* match */ }
Important: == on char* compares the addresses, not the contents — you must use strcmp for value comparison. (For non-null-terminated or binary data, memcmp; for length-bounded string compare, strncmp.) The interview answer: strcmp() — returns 0 on equality, negative/positive for ordering.
Answer:
strcmp().
strcmp(s1, s2) compares two C strings lexicographically (byte-by-byte by character value):
- Returns
0if the strings are equal. - Returns negative if
s1 < s2. - Returns positive if
s1 > s2.
if (strcmp(str, "quit") == 0) { /* match */ }
Important: == on char* compares the addresses, not the contents — you must use strcmp for value comparison. (For non-null-terminated or binary data, memcmp; for length-bounded string compare, strncmp.) The interview answer: strcmp() — returns 0 on equality, negative/positive for ordering.
4. What problem arises from using strcpy(dest, src) without prior length verification?
Answer: A buffer overflow — if src is longer than dest’s capacity, strcpy writes past the end, corrupting surrounding memory.
strcpy(dest, src) copies bytes until it hits a '\0' in src — with no bounds checking on dest. If src is longer than the destination buffer can hold:
- Bytes spill past
dest’s end into adjacent memory — other variables, saved return addresses, heap metadata. - Result: crashes, subtle data corruption, or security exploits (stack-smashing attacks that overwrite the return address).
char buf[10];
strcpy(buf, "this string is way too long"); // overflow
Safe alternatives: strncpy (bounded, but doesn’t guarantee null-termination) or better, snprintf(dest, size, "%s", src) which always null-terminates and respects the size. The interview answer: unbounded copy → stack/heap buffer overflow, memory corruption, and potential code-execution exploits.
Answer:
A buffer overflow — if src is longer than dest’s capacity, strcpy writes past the end, corrupting surrounding memory.
strcpy(dest, src) copies bytes until it hits a '\0' in src — with no bounds checking on dest. If src is longer than the destination buffer can hold:
- Bytes spill past
dest’s end into adjacent memory — other variables, saved return addresses, heap metadata. - Result: crashes, subtle data corruption, or security exploits (stack-smashing attacks that overwrite the return address).
char buf[10];
strcpy(buf, "this string is way too long"); // overflow
Safe alternatives: strncpy (bounded, but doesn’t guarantee null-termination) or better, snprintf(dest, size, "%s", src) which always null-terminates and respects the size. The interview answer: unbounded copy → stack/heap buffer overflow, memory corruption, and potential code-execution exploits.
5. What does strtok() modify during string tokenization execution?
Answer: It modifies the input string in place, replacing each delimiter with a '\0' terminator and returning pointers to the resulting tokens.
strtok tokenizes a string on the fly. Its mechanics are unusual:
- The first call takes the source string; subsequent calls pass
NULLto continue from where the previous call left off (the function keeps internal static state). - Each delimiter character in the input is overwritten with
'\0', so the original string is mutated. - It returns pointers into that same buffer — no new memory is allocated.
char s[] = "apple,banana,cherry";
char *tok = strtok(s, ","); // "apple"
tok = strtok(NULL, ","); // "banana"
tok = strtok(NULL, ","); // "cherry"
Consequences: the source must be a mutable array (not a string literal — writing to literals is UB), and the internal static state makes strtok not thread-safe (strtok_r is the reentrant version). The interview answer: strtok mutates the source in place, writing '\0' over delimiters and returning token pointers into the same buffer.
Answer:
It modifies the input string in place, replacing each delimiter with a '\0' terminator and returning pointers to the resulting tokens.
strtok tokenizes a string on the fly. Its mechanics are unusual:
- The first call takes the source string; subsequent calls pass
NULLto continue from where the previous call left off (the function keeps internal static state). - Each delimiter character in the input is overwritten with
'\0', so the original string is mutated. - It returns pointers into that same buffer — no new memory is allocated.
char s[] = "apple,banana,cherry";
char *tok = strtok(s, ","); // "apple"
tok = strtok(NULL, ","); // "banana"
tok = strtok(NULL, ","); // "cherry"
Consequences: the source must be a mutable array (not a string literal — writing to literals is UB), and the internal static state makes strtok not thread-safe (strtok_r is the reentrant version). The interview answer: strtok mutates the source in place, writing '\0' over delimiters and returning token pointers into the same buffer.
6. How does snprintf() protect against buffer overflow compared to sprintf()?
Answer: snprintf(buf, size, fmt, ...) caps output at size - 1 bytes and always appends a '\0'; sprintf() writes without limit.
sprintf(buf, fmt, ...) formats and copies the entire result into buf with no bounds check — a long formatted result overflows the buffer (the classic overflow vector).
snprintf takes an explicit buffer size and guarantees:
- At most
size - 1bytes of formatted output are written (room for the null terminator). - The result is always null-terminated (unless
sizeis 0).
char buf[64];
snprintf(buf, sizeof(buf), "%s", long_string); // safely truncated, terminated
The return value (what would have been written) lets you detect truncation. Modern guidance: prefer snprintf (and its sibling vsnprintf) over sprintf everywhere. The interview answer: snprintf writes at most size - 1 bytes plus a null terminator, preventing overruns.
Answer:
snprintf(buf, size, fmt, ...) caps output at size - 1 bytes and always appends a '\0'; sprintf() writes without limit.
sprintf(buf, fmt, ...) formats and copies the entire result into buf with no bounds check — a long formatted result overflows the buffer (the classic overflow vector).
snprintf takes an explicit buffer size and guarantees:
- At most
size - 1bytes of formatted output are written (room for the null terminator). - The result is always null-terminated (unless
sizeis 0).
char buf[64];
snprintf(buf, sizeof(buf), "%s", long_string); // safely truncated, terminated
The return value (what would have been written) lets you detect truncation. Modern guidance: prefer snprintf (and its sibling vsnprintf) over sprintf everywhere. The interview answer: snprintf writes at most size - 1 bytes plus a null terminator, preventing overruns.
7. What is the cause of “Undefined Behavior” when using strcpy(dest, src) on overlapping memory strings?
Answer: The C standard explicitly leaves strcpy undefined for overlapping buffers — it copies sequentially, so a copy can overwrite source bytes before they’re read.
strcpy copies characters one by one from src to dest until the null terminator, with no intermediate buffering. If the regions overlap:
- The destination’s early bytes can overwrite source bytes that haven’t been copied yet.
- The copied result is corrupt (or worse), and the standard says the behavior is undefined — no guarantee at all.
Example that breaks: strcpy(s + 1, s) — shifting a string right by one — overwrites s[1] (the second char of source) before it’s read.
The fix: memmove for overlapping regions (it copies safely, as if via a temp buffer), or strcpy only for provably disjoint buffers. The interview answer: strcpy copies sequentially with no temporary buffering, so overlapping source/destination is undefined per the standard.
Answer:
The C standard explicitly leaves strcpy undefined for overlapping buffers — it copies sequentially, so a copy can overwrite source bytes before they’re read.
strcpy copies characters one by one from src to dest until the null terminator, with no intermediate buffering. If the regions overlap:
- The destination’s early bytes can overwrite source bytes that haven’t been copied yet.
- The copied result is corrupt (or worse), and the standard says the behavior is undefined — no guarantee at all.
Example that breaks: strcpy(s + 1, s) — shifting a string right by one — overwrites s[1] (the second char of source) before it’s read.
The fix: memmove for overlapping regions (it copies safely, as if via a temp buffer), or strcpy only for provably disjoint buffers. The interview answer: strcpy copies sequentially with no temporary buffering, so overlapping source/destination is undefined per the standard.
8. What is the purpose of string function strcspn(s1, s2)?
Answer: It returns the length of the initial segment of s1 consisting of characters NOT in s2.
strcspn(s1, s2) scans s1 from the start and counts characters until it hits one that appears in s2:
strcspn("hello world", " ") // 5 — stops at the space
strcspn("abc123", "xyz") // 6 — no x/y/z found, counts all of s1
Think “complement span not” — the span of s1 that is the complement of (not in) s2. Its sibling strspn(s1, s2) counts the initial segment consisting only of characters in s2. Use cases: finding the first occurrence of any of a set of characters (the return value is the index), parsing delimiters. The interview answer: the length of s1’s prefix that contains no characters from s2.
Answer:
It returns the length of the initial segment of s1 consisting of characters NOT in s2.
strcspn(s1, s2) scans s1 from the start and counts characters until it hits one that appears in s2:
strcspn("hello world", " ") // 5 — stops at the space
strcspn("abc123", "xyz") // 6 — no x/y/z found, counts all of s1
Think “complement span not” — the span of s1 that is the complement of (not in) s2. Its sibling strspn(s1, s2) counts the initial segment consisting only of characters in s2. Use cases: finding the first occurrence of any of a set of characters (the return value is the index), parsing delimiters. The interview answer: the length of s1’s prefix that contains no characters from s2.
9. What does the string conversion function strtol() provide compared to atoi()?
Answer: strtol() provides error detection (invalid input, overflow via errno) and arbitrary base conversion; atoi() is a bare parser with no error reporting.
atoi(str)— converts toint, but on failure returns0with no way to distinguish “the string was"0"” from “invalid input,” and no overflow detection.strtol(str, &endptr, base)— full-featured:- Error detection: sets
errnotoERANGEon overflow/underflow and returnsLONG_MAX/LONG_MIN;endptrpoints past the consumed digits, so you can verify the whole string was parsed (*endptr == '\0'). - Base selection:
base2–36 (hex0x, octal0, decimal10, or0= auto-detect by prefix).
- Error detection: sets
char *end;
errno = 0;
long v = strtol(s, &end, 10);
if (errno == ERANGE) /* overflow */;
if (end == s) /* no digits consumed */;
The interview answer: strtol detects errors (via errno/endptr) and supports arbitrary bases; atoi has neither.
Answer:
strtol() provides error detection (invalid input, overflow via errno) and arbitrary base conversion; atoi() is a bare parser with no error reporting.
atoi(str)— converts toint, but on failure returns0with no way to distinguish “the string was"0"” from “invalid input,” and no overflow detection.strtol(str, &endptr, base)— full-featured:- Error detection: sets
errnotoERANGEon overflow/underflow and returnsLONG_MAX/LONG_MIN;endptrpoints past the consumed digits, so you can verify the whole string was parsed (*endptr == '\0'). - Base selection:
base2–36 (hex0x, octal0, decimal10, or0= auto-detect by prefix).
- Error detection: sets
char *end;
errno = 0;
long v = strtol(s, &end, 10);
if (errno == ERANGE) /* overflow */;
if (end == s) /* no digits consumed */;
The interview answer: strtol detects errors (via errno/endptr) and supports arbitrary bases; atoi has neither.
10. What is the result of applying sizeof(“Hello”) in C?
Answer: 6 — the 5 characters plus the implicit null terminator '\0'.
A string literal is stored as an array of char including a terminating '\0'. "Hello" is {'H','e','l','l','o','\0'} — 6 bytes. So sizeof("Hello") is 6.
The common trap: strlen("Hello") returns 5 (it counts up to, but not including, the null terminator). The difference between sizeof and strlen for literals is exactly the +1 for the terminator. The interview answer: 6 — the 5 characters plus the null terminator.
Answer:
6 — the 5 characters plus the implicit null terminator '\0'.
A string literal is stored as an array of char including a terminating '\0'. "Hello" is {'H','e','l','l','o','\0'} — 6 bytes. So sizeof("Hello") is 6.
The common trap: strlen("Hello") returns 5 (it counts up to, but not including, the null terminator). The difference between sizeof and strlen for literals is exactly the +1 for the terminator. The interview answer: 6 — the 5 characters plus the null terminator.
Premium Content
Unlock Strings and all premium lessons with a subscription.
From ₹199.99/year — See plans