Skip to content
Home C / C++ C Strings — Null Terminator Forgotten: The 3 AM Pager

C Strings — Null Terminator Forgotten: The 3 AM Pager

Where developers are forged. · Structured learning · Free forever.
📍 Part of: C Basics → Topic 7 of 17
Forgotten null terminator after strncpy? Production crashes with longer names.
🧑‍💻 Beginner-friendly — no prior C / C++ experience needed
In this tutorial, you'll learn
Forgotten null terminator after strncpy? Production crashes with longer names.
  • A C string is just a char array in contiguous memory with a '\0' byte at the end — there's no magic, just a convention every standard function depends on.
  • strlen() and sizeof() measure different things: strlen counts characters before the null terminator; sizeof counts the total bytes of the array variable including the null terminator.
  • Never use gets() or unconstrained scanf("%s") for user input — use fgets(buffer, sizeof(buffer), stdin) to prevent buffer overflows.
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
Quick Answer
  • C strings are char arrays terminated by a null byte (\0).
  • No built-in length field — strlen() walks the array O(n) each time.
  • Buffer overflows happen when copying to an undersized destination.
  • Use fgets() instead of gets() or scanf("%s") for safe input.
  • sizeof gives total array bytes; strlen gives character count — they differ by 1.
🚨 START HERE

String Bug First-Response Command Deck

Run these commands when the on-call page blinks red because of a string bug.
🟡

Segfault on printf with a pointer variable

Immediate ActionRestart with AddressSanitizer enabled
Commands
gcc -fsanitize=address -g -o myprog myprog.c && ./myprog
tail -100 /var/log/syslog | grep segfault
Fix NowEnsure the pointer is non-null and points to a properly null-terminated string.
🟡

Buffer overflow causing silent data corruption

Immediate ActionFind every strcpy and strcat call in the codebase
Commands
grep -rn 'strcpy\|strcat' src/ | grep -v 'strncpy\|strlcat'
check each call against the destination buffer size (use sizeof or documented bounds)
Fix NowReplace with snprintf(dest, sizeof(dest), "%s", src) and manually null-terminate.
🟡

fgets reads past buffer?

Immediate ActionVerify the second argument is correct: fgets(buf, sizeof(buf), stdin)
Commands
printf("sizeof buf = %zu\n", sizeof(buf)); // must be an array, not a pointer
check for leftover newline: if (strchr(buf, '\n')) /* strip it */
Fix NowAlways use fgets(buf, sizeof(buf), stdin) and strip the newline with strcspn.
Production Incident

Null Terminator Forgotten: The 3 AM Pager

A team spent 6 hours debugging a segfault that only happened once every 10,000 transactions. Root cause: one missing null terminator after a manual string copy.
SymptomApplication crashes intermittently with segmentation fault when processing user-supplied name fields. The crash rate increases with longer names.
AssumptionThe team assumed their strncpy call automatically null-terminated the destination buffer. They relied on man pages that described strncpy behaviour but missed the edge case: when the source is longer than the buffer, no null terminator is written.
Root causeA call to strncpy(dest, src, sizeof(dest)) without manually adding a \0 at the end. When src was exactly sizeof(dest) characters or longer, dest had no null terminator. The next printf() or strcat() on dest read past the buffer into adjacent memory, corrupting stack frames.
FixAlways add dest[sizeof(dest) - 1] = '\0'; after any strncpy or strlcpy call. Better yet: use snprintf() which guarantees null termination as long as the buffer size is correct.
Key Lesson
strncpy does NOT null-terminate if the source fills the destination.After every bounded string copy, manually ensure the last byte is 0.Treat every string buffer as potentially not null-terminated until you prove otherwise.
Production Debug Guide

Diagnose the most common C string failures in live systems

Segfault at memory address 0x0 or near random addressesCheck for null pointers passed to string functions. Run with AddressSanitizer (ASan) to pinpoint the exact overflow location.
Output contains garbage characters or data corruption after strcat/strcpyVerify the destination buffer has room for the source plus null terminator. Use [snprintf](dest, sizeof(dest), "%s%s", existing, append) instead of strcat.
String comparison returns unexpected falseCheck for trailing newline from fgets() — it's included in the buffer. Strip it with buffer[strcspn(buffer, "\n")] = 0;.
Intermittent crashes only with large inputsSuspect a buffer that was sized for test data but not for production. Search for malloc(strlen(x)) without the +1 for the null terminator.

Every program that talks to a human needs text. Whether it's a login prompt, an error message, a username, or a file path — text is everywhere. In languages like Python or JavaScript, strings are cosy, fully managed objects that do a lot of heavy lifting for you. C, on the other hand, hands you the raw tools and trusts you to build the house yourself. That might sound scary, but understanding how C handles text under the hood makes you a dramatically better programmer in any language.

The core problem C strings solve is deceptively simple: how do you store a sequence of characters in memory and then find where that sequence ends? Memory is just a giant numbered grid of bytes. There's no built-in concept of 'a word' or 'a sentence'. C's answer is a convention called the null-terminated string — store your characters in consecutive memory slots and place a special zero-value byte at the end as a sentinel. Every standard library function that works with strings relies on this single rule.

By the end of this article you'll know exactly how C strings are stored in memory, how to declare and initialise them correctly, how to manipulate them using the standard library, and — most importantly — how to avoid the buffer overflows and undefined behaviour that trip up even experienced developers. You'll be reading real code, seeing real output, and walking away with a mental model that actually sticks.

What a C String Actually Is in Memory

A C string is not a special type — it's just a pointer to a sequence of 'char' values stored in contiguous memory, where the last character is always '\0' (the null terminator, ASCII value 0). That's it. There's no hidden length field, no magic object — just raw bytes in a row.

Think of RAM as a long street of numbered houses. Each house holds one character. When C stores the word 'Hello', it rents five houses in a row — one for 'H', one for 'e', one for 'l', one for 'l', one for 'o' — and then immediately rents one more house where it places a STOP sign (the '\0'). So 'Hello' actually occupies 6 bytes, not 5.

This is why the length of a string and the memory it needs are different numbers. strlen() counts the characters before the stop sign. sizeof() tells you the total space including the stop sign. Confusing these two is one of the most common beginner mistakes, so burn that distinction into your memory right now.

Whenever a standard library function like printf or strcpy reads a C string, it starts at the first character and keeps going until it hits that '\0'. That's the contract every piece of C string code relies on. Break that contract — forget the null terminator — and your program wanders into memory it doesn't own.

string_memory_layout.c · C
1234567891011121314151617181920212223
#include <stdio.h>
#include <string.h>

void io_thecodeforge_debug_string_memory() {
    char greeting[] = "Hello";
    size_t char_count = strlen(greeting);
    size_t byte_count = sizeof(greeting);

    printf("String: %s\n", greeting);
    printf("strlen: %zu (visible chars)\n", char_count);
    printf("sizeof: %zu (total memory bytes)\n", byte_count);

    printf("\nByte Map:\n");
    for (size_t i = 0; i < byte_count; i++) {
        printf("  index [%zu]: '%c' (Hex: 0x%02X)\n", 
               i, (greeting[i] ? greeting[i] : '?'), (unsigned char)greeting[i]);
    }
}

int main(void) {
    io_thecodeforge_debug_string_memory();
    return 0;
}
▶ Output
String: Hello
strlen: 5 (visible chars)
sizeof: 6 (total memory bytes)

Byte Map:
index [0]: 'H' (Hex: 0x48)
index [1]: 'e' (Hex: 0x65)
index [2]: 'l' (Hex: 0x6C)
index [3]: 'l' (Hex: 0x6C)
index [4]: 'o' (Hex: 0x6F)
index [5]: '?' (Hex: 0x00)
⚠ Watch Out: strlen vs sizeof
Never use sizeof() to get the number of characters in a string — use strlen(). sizeof gives you the byte size of the array variable, not the logical length. They're only the same for single-character strings by coincidence. This mix-up causes off-by-one bugs that are incredibly hard to track down.
📊 Production Insight
A missing null terminator is the #1 cause of silent data corruption in C programs.
Rule: after any manual character fill, always set the final byte to 0.
When in doubt, print all 256 bytes of the buffer and look for the 0x00 marker.
🎯 Key Takeaway
strlen counts characters before \0; sizeof counts total bytes including \0.
This difference causes the most common off-by-one error in C.
Always remember: char arrays need one extra byte for the null terminator.
When to Check strlen vs sizeof
IfYou need the number of characters in a string (logical length)
UseUse strlen(str) — it walks until '\0'.
IfYou need the total memory allocated for the array
UseUse sizeof(arr) — only works on array, not on pointer.
IfYou're passing a string to a function (decays to pointer)
Usesizeof gives pointer size (8 bytes on 64-bit), useless for length.

Three Ways to Declare a String — and Which One to Use When

C gives you three different ways to create a string, and each one behaves differently in memory. Picking the wrong one at the wrong time is a classic source of bugs.

The first way is a character array initialised with a string literal: 'char name[] = "Alice";'. The compiler figures out the right size, copies the characters including the null terminator into stack memory, and gives you a mutable buffer you can change. This is the go-to choice when you need to modify the string later.

The second way is to give the array an explicit size: 'char name[50] = "Alice";'. Now you've got 50 bytes reserved, with 'Alice\0' at the start and the rest zeroed out. This is what you want when you're planning to read user input into the buffer — you're pre-allocating the space.

The third way is a pointer to a string literal: 'const char *message = "Hello";'. This does NOT copy the string into a regular variable. Instead, the string 'Hello\0' lives in a read-only section of your program's memory, and 'message' is just a pointer to it. Trying to modify this string causes undefined behaviour — the program might crash, might silently corrupt data, or might appear to work fine on your machine and explode on someone else's. Always mark these 'const'.

string_declarations.c · C
1234567891011121314151617181920
#include <stdio.h>
#include <string.h>

int main(void) {
    // 1. Stack Array (Mutable)
    char mutable_str[] = "Forge";
    mutable_str[0] = 'f'; // Valid

    // 2. Pre-allocated Buffer
    char buffer[128] = "io.thecodeforge";

    // 3. String Literal Pointer (Read-Only)
    const char *readonly_msg = "Strictly Read Only";

    printf("Array: %s\n", mutable_str);
    printf("Buffer: %s\n", buffer);
    printf("Pointer: %s\n", readonly_msg);

    return 0;
}
▶ Output
Array: forge
Buffer: io.thecodeforge
Pointer: Strictly Read Only
🔥Pro Tip: Always Use const for Literal Pointers
The compiler won't always stop you from writing 'char msg = "hello";' (without const), but it's lying to you — that memory is read-only at runtime. Always write 'const char msg = "hello";'. It makes your intent clear, and modern compilers will warn you if you accidentally try to modify it.
📊 Production Insight
Using a non-const pointer to a string literal compiles without error in C (in C++ it warns).
The program runs fine until some code path attempts to write to it — then segfault.
Rule: always declare pointer-to-literal with const. Never relax it.
🎯 Key Takeaway
Three ways, three different memory behaviours.
const char * is read-only; char[] is mutable; char[SIZE] is pre-sized.
Pick based on mutability needs, not habit.
Choose Your Declaration Strategy
IfYou need to modify the string later (e.g., uppercase conversion)
UseUse char arr[] = "..." or char arr[SIZE] = "..." for mutable buffer.
IfYou need a large buffer for user input
UseUse char buf[SIZE] with an explicit size, and pass sizeof(buf) to fgets.
IfYou want a fixed message that never changes
UseUse const char *msg = "..." — no copy, read-only, efficient.

The Essential String Functions You'll Use Every Day

C's standard library ships with a set of string functions in <string.h> that cover the operations you'll need constantly — measuring length, copying, joining, comparing, and searching. They're thin, fast, and they all depend on that null terminator contract we talked about.

strlen(s) walks the string from the start until it hits '\0' and returns how many steps it took. O(n) — it actually loops through every character each time you call it, so don't call it inside a loop's condition if you can avoid it.

strcpy(destination, source) copies every character from source into destination, including the final '\0'. The danger: it blindly trusts that destination is big enough. If it isn't, you've just written past the end of your buffer — a classic buffer overflow. Prefer strncpy or snprintf for safer copying.

strcmp(a, b) returns 0 if the strings are identical, a negative number if a comes before b alphabetically, and a positive number if a comes after b. Do NOT use == to compare strings in C — it compares pointer addresses, not content.

strstr(haystack, needle) finds the first occurrence of 'needle' in 'haystack' and returns a pointer to it, or NULL if not found. It's O(n*m) in the worst case, but fine for short strings.

string_functions_demo.c · C
123456789101112131415161718192021222324
#include <stdio.h>
#include <string.h>

int main(void) {
    const char *src = "thecodeforge";
    char dest[20];

    // Safe Copying
    strncpy(dest, src, sizeof(dest) - 1);
    dest[sizeof(dest) - 1] = '\0'; // Manual safety termination

    // Comparison
    if (strcmp(dest, "thecodeforge") == 0) {
        printf("Strings match exactly.\n");
    }

    // Substring Search
    char *found = strstr(dest, "forge");
    if (found) {
        printf("Found substring at index: %ld\n", found - dest);
    }

    return 0;
}
▶ Output
Strings match exactly.
Found substring at index: 7
💡Interview Gold: Why Can't You Use == to Compare Strings?
Because in C, a string variable is a pointer. Writing 'str1 == str2' compares the memory addresses the two pointers point to, not the characters they contain. Two strings with identical content can sit at different addresses and return false. Always use strcmp() — and always check its return value against 0, not just treat it as a boolean.
📊 Production Insight
Calling strlen() inside a loop condition turns O(n) into O(n²).
Store the length in a variable before the loop.
Rule: compute strlen once, reuse. Your CPU will thank you.
🎯 Key Takeaway
strlen is O(n), strcpy is dangerous, strcmp is correct.
Never use == to compare strings. Use snprintf for safe concatenation.
Always null-terminate after bounded copies.
Choosing a Copy Function
IfYou know the source fits safely in the destination
UseUse strcpy() — it's the fastest, but only when guaranteed safe.
IfYou don't know the source length
UseUse strncpy(dest, src, dest_size) AND manually null-terminate.
IfYou're building a formatted string
UseUse snprintf(dest, dest_size, "%s%s", ...) — it null-terminates automatically.

Reading Strings from the User Safely with fgets

This is where beginners cause the most damage. The classic first instinct is to use scanf("%s", buffer) to read a string from the keyboard. It works — until your user types more characters than your buffer holds, and now you've written past the end of your array into memory you don't own. That's a buffer overflow, and it's one of the most exploited classes of security vulnerabilities in the history of software.

fgets is the safe alternative. It takes three arguments: the buffer to write into, the maximum number of bytes to read (including the null terminator), and the stream to read from (stdin for keyboard input). It will never write more than that maximum, so your buffer stays intact.

One quirk: fgets includes the newline character (' ') if space allows. So if the user types "hello" and presses Enter, the buffer will contain "hello \0". You almost always want to strip that newline before processing. The idiomatic way: buffer[strcspn(buffer, " ")] = 0; which replaces the first newline with a null terminator.

safe_string_input.c · C
123456789101112131415161718
#include <stdio.h>
#include <string.h>

int main(void) {
    char input_buffer[32];

    printf("Enter code tag: ");

    // fgets is safe; prevents reading more than 32 bytes
    if (fgets(input_buffer, sizeof(input_buffer), stdin)) {
        // Strip the trailing newline often left by enter key
        input_buffer[strcspn(input_buffer, "\n")] = 0;
        
        printf("Processing: [%s]\n", input_buffer);
    }

    return 0;
}
▶ Output
Enter code tag: feature-request
Processing: [feature-request]
⚠ Watch Out: Never Use gets()
gets() was removed from the C11 standard because it cannot be used safely — there is no way to tell it your buffer size, so any input longer than the buffer causes undefined behaviour. Every major OS lists gets-based code as a security vulnerability. Use fgets(buffer, sizeof(buffer), stdin) every single time.
📊 Production Insight
scanf("%s") is as dangerous as gets() if not constrained.
It writes past the buffer without limit. Use fgets() always.
Rule: if you see scanf("%s") in a code review, flag it immediately.
🎯 Key Takeaway
fgets() is your only safe option for text input.
Always strip the newline after fgets.
Never, ever use gets(). It will exploit your users.
Input Reading Decision
IfReading a line of text from stdin
UseUse fgets(buf, sizeof(buf), stdin) and strip newline.
IfReading formatted values (ints, floats)
UseUse scanf() but with width specifiers, e.g., scanf("%32s", buf).
IfReading from a file
UseUse fgets() for lines; fread() for raw data.

Common Pitfalls and Debugging Strategies for C Strings

Even experienced C developers hit string bugs. The most insidious ones involve off-by-one errors, improperly terminated buffers, and mixing array sizes with pointer sizes. Here's a breakdown of the patterns that cause production outages.

Off-by-one: You allocate char buf[10] for a 10-character string, but you need 11 (10 chars + null). This is the classic BUFSIZ+1 mistake. Always allocate expected_length + 1.

Pointer decay: When you pass an array to a function, sizeof(arr) inside the function gives you the pointer size, not the array size. This breaks any code that uses sizeof to bound a copy. Solution: pass the array size as a separate parameter.

Uninitialized buffers: A local char buf[100]; contains garbage. If you don't null-terminate before using it with string functions, they'll read past the intended data. Always initialize with = {0} or buf[0] = '\0'.

Strcat without checking space: strcat appends to the destination. If the destination already contains data, the total must fit. Use strncat(dest, src, sizeof(dest) - strlen(dest) - 1) or better, snprintf. Note: strncat takes the number of characters to append, not the total buffer size — different from strncpy!

debugging_patterns.c · C
12345678910111213141516
#include <stdio.h>
#include <string.h>

void io_thecodeforge_safe_concat(char *dest, size_t dest_size, const char *src) {
    size_t dest_len = strlen(dest);
    size_t available = dest_size - dest_len - 1;
    strncat(dest, src, available);
    dest[dest_size - 1] = '\0'; // safety
}

int main(void) {
    char buf[64] = "Hello ";
    io_thecodeforge_safe_concat(buf, sizeof(buf), "World!");
    printf("%s\n", buf);
    return 0;
}
▶ Output
Hello World!
Mental Model
The +1 Rule
Every string buffer needs space for the null terminator — always allocate one extra byte.
  • If you need to store N characters, allocate N+1 bytes.
  • strlen returns N, sizeof gives N+1 (only for arrays).
  • fgets reads at most N-1 characters, then adds \0 (N total).
  • snprintf returns the number of bytes that would be written (excluding \0) — check if >= buffer size.
📊 Production Insight
The most subtle string bug: using sizeof on a pointer passed to a function.
Inside the function, sizeof(ptr) yields pointer size (8 bytes), not array size.
Always pass the buffer size explicitly as a parameter.
Rule: char *str, size_t str_size should be your default parameter pattern.
🎯 Key Takeaway
Off-by-one, pointer decay, and uninitialised buffers are the top three killers.
Always allocate +1 for null.
Pass sizes explicitly around functions.
Initialize all buffers to zero.
🗂 char array vs char pointer
Which declaration style to use and why
Aspectchar array (char name[])char pointer (const char *)
Memory locationStack (local) or data segmentRead-only data segment
Can you modify the content?Yes — it's your bufferNo — undefined behaviour if you try
Size known at compile time?Yes — sizeof() works correctlyNo — sizeof() gives pointer size, not string length
Good for user input?Yes — use with fgets()No — never point this at mutable input
Good for fixed messages?Works, but wastes a copyYes — ideal, mark const
Null terminator required?Yes, alwaysYes, always — it's the law of C strings
Comparison methodstrcmp() onlystrcmp() only
Common beginner trapForgetting to allocate +1 for nullTrying to modify without const warning

🎯 Key Takeaways

  • A C string is just a char array in contiguous memory with a '\0' byte at the end — there's no magic, just a convention every standard function depends on.
  • strlen() and sizeof() measure different things: strlen counts characters before the null terminator; sizeof counts the total bytes of the array variable including the null terminator.
  • Never use gets() or unconstrained scanf("%s") for user input — use fgets(buffer, sizeof(buffer), stdin) to prevent buffer overflows.
  • Always use strcmp() to compare strings, never == — strings are pointers, and == compares addresses, not the characters they point to.
  • Memory for strings must always be allocated with +1 byte for the null terminator — forget it and you get buffer overflows or undefined behaviour.

⚠ Common Mistakes to Avoid

    Forgetting to allocate space for the null terminator
    Symptom

    char word[5] = "Hello"; — the compiler either rejects it or silently omits the null terminator, causing every string function call to read garbage past the array.

    Fix

    Declare char arrays with length = expected characters + 1, or let the compiler count with 'char word[] = "Hello";'.

    Using == to compare strings
    Symptom

    if (input == "yes") compares two memory addresses, almost always false even when content matches, leading to logic bugs.

    Fix

    Always use 'strcmp(input, "yes") == 0' — the return value of 0 means the strings are identical.

    Using strcpy or strcat without checking buffer capacity
    Symptom

    When source is longer than destination, these functions write past the end of your array, overwriting adjacent variables or return addresses — a buffer overflow.

    Fix

    Use strncpy(dest, src, sizeof(dest) - 1) followed by 'dest[sizeof(dest)-1] = '\0';' or use snprintf() for building strings.

    Confusing sizeof and strlen
    Symptom

    Using sizeof(buf) when buffer is a pointer parameter gives 8 on 64-bit systems, not the actual buffer size, causing incorrect copy bounds.

    Fix

    Always pass the buffer size as a separate parameter. Never rely on sizeof() inside a function that receives a pointer.

Interview Questions on This Topic

  • QHow does the null-terminator affect the time complexity of the strlen() function? Why is it O(n) and not O(1)?JuniorReveal
    strlen() must walk through the array from the start until it finds the '\0' byte. Since there's no length prefix (like in Pascal or Java strings), the function cannot know where the string ends without scanning. That makes it O(n) where n is the number of characters. Calling strlen inside a loop condition (e.g., for (i=0; i<strlen(s); i++)) turns the entire operation O(n²). Always store the length in a variable before the loop.
  • QExplain why 'char *p = "Hello"; p[0] = 'h';' leads to a Segmentation Fault on most modern operating systems.JuniorReveal
    The string literal "Hello" is stored in a read-only data section (usually .rodata) of the program's memory. The pointer p points to that immutable memory. Attempting to write to it triggers a page fault because the memory page is marked read-only by the OS. The fix is to either use an array (char p[] = "Hello") or mark the pointer const (const char *p = "Hello") to let the compiler catch this mistake.
  • QGiven a character array char buf[10], what happens if you attempt to store the string "IDENTIFICATION" using strcpy? Describe the impact on the stack frame.Mid-levelReveal
    The string "IDENTIFICATION" is 16 characters plus null terminator = 17 bytes. strcpy will copy all 17 bytes into buf, which only has 10 bytes of allocated space. It overwrites the 7 bytes (or more, depending on alignment) past the end of buf on the stack. This corrupts adjacent local variables and, crucially, the saved return address. When the function returns, execution jumps to the corrupted address — this is a classic buffer overflow exploit vector. Tools like StackGuard and AddressSanitizer detect this exact scenario.
  • QHow would you implement a basic version of strlen without using any library functions? Write the code using a while loop and pointer arithmetic.JuniorReveal
    ``c #include <stddef.h> size_t io_thecodeforge_strlen(const char s) { const char p = s; while (p) { p++; } return p - s; } ` This uses a pointer to traverse until it hits the null terminator. The difference between the final pointer and the start gives the number of characters. Note: p` is true for all non-zero characters, and false for '\0' (ASCII 0). This is linear time O(n).
  • QWhat is the 'Off-by-one' error specifically related to C strings and the null terminator? Give a concrete example.JuniorReveal
    The off-by-one error occurs when you allocate a buffer of size N to hold a string of N characters, forgetting that the null terminator requires an additional byte. For example: char buf[5] = "hello"; — This is wrong because "hello" actually needs 6 bytes (5 characters + '\0'). With size 5, the compiler either rejects it (C99+) or stores without the null terminator (C89). The correct declaration is char buf[] = "hello"; (compiler counts 6) or char buf[6] = "hello";. This error is why you always see patterns like char buf[BUFSIZ+1].

Frequently Asked Questions

What is a null terminator in C strings and why is it needed?

The null terminator is a byte with the value zero ('\0') placed at the end of every C string. Because C has no built-in string type and strings are just arrays of characters in raw memory, the null terminator is the only signal that tells functions like printf, strlen, and strcpy where the string ends. Without it, those functions keep reading memory past your string until they accidentally find a zero byte somewhere, causing unpredictable bugs.

What is the difference between a string literal and a char array in C?

A string literal like "Hello" is stored in a read-only section of your program's memory and should never be modified. A char array like 'char greeting[] = "Hello";' copies those characters into a mutable buffer on the stack that you can freely change. The literal is the source of truth; the array is your working copy.

Why does sizeof() give the wrong length for a string pointer in C?

When you have 'const char *msg = "Hello";', msg is a pointer variable — typically 8 bytes on a 64-bit system. sizeof(msg) gives you the size of the pointer itself, not the size of the string it points to. To get the character count of the string, use strlen(msg). This is one of the most common beginner confusions in C.

How do I clear a C string buffer efficiently?

The most common way is using memset(buffer, 0, sizeof(buffer)); which fills the entire array with null characters. Alternatively, simply setting buffer[0] = '\0'; effectively makes it an 'empty' string from the perspective of standard C functions, though the old data remains in the subsequent memory slots.

What's the difference between strncpy and strncat?

strncpy(dest, src, n) copies at most n bytes from src to dest, but if src is shorter, it pads the rest with nulls. It does NOT guarantee null termination if src length >= n. strncat(dest, src, n) appends at most n characters from src to the end of dest (after its existing null terminator) and then adds a null terminator. The n in strncat is the number of characters to append, not the total buffer size — a frequent point of confusion.

🔥
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← PreviousArrays in CNext →Pointers in C
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged