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
95: String Length and Copying: strlen, strcpy, strncpy
A few years ago, I was reviewing a junior dev's code for a network packet parser. He had a fixed-size buffer of 64 bytes to hold a "Sender Name" string coming over the wire. He used strcpy to move the data from the raw packet into a local variable. It worked perfectly during testing—until a malicious actor sent a packet with a 200-character name. The program didn't just crash; it overwrote the return address on the stack, leading to a classic buffer overflow vulnerability. It was a stark reminder that in C, the language assumes you know exactly what you're doing, even when you're doing something that's fundamentally dangerous.
Counting characters with strlen
Before you can move or manipulate a string, you usually need to know how big it is. That's where strlen comes in. The most important thing to remember here is that strlen counts the number of characters before the null terminator (\0). It does not include the terminator itself in the count.
char username[] = "DevMaster99";
size_t len = strlen(username);
// len will be 11, even though the array size is actually 12.
I always remind people to use size_t for the return type. Since a string can't have a negative length, using a signed int is technically incorrect and can lead to warnings or bugs when dealing with massive buffers. Just keep in mind that strlen has to scan the entire string to find that null terminator, so if you're calling it inside a loop condition, you might be accidentally turning an O(n) operation into O(n²). Cache the length in a variable first.
The risks of strcpy
When you want to duplicate a string, strcpy is the most direct route. It copies the source string, including the null terminator, into the destination. But here is the catch: strcpy has no idea how big the destination buffer is. It will keep writing bytes into memory until it hits a \0 in the source string. If your source is larger than your destination, you're overwriting other variables, the stack frame, or whatever else happens to be next in memory.
char dest[10];
char src[] = "This string is way too long!";
strcpy(dest, src); // Memory corruption happens right here.
In a professional production environment, you'll almost never see strcpy used on data that comes from an external source (like user input or a network socket). It's simply too risky. It's a "trusting" function, and in systems programming, trusting your input is a recipe for disaster.
Controlling the copy with strncpy
To fix the danger of strcpy, we use strncpy. The 'n' stands for the maximum number of characters to copy. This gives you a way to enforce a boundary, ensuring you don't write past the end of your allocated buffer.
char dest[10];
char src[] = "This string is way too long!";
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0'; // The critical manual step
Now, pay close attention to that last line. This is the "gotcha" that trips up almost every C student. If the source string is longer than or equal to the limit you provide to strncpy, the function will copy the characters but will not append a null terminator to the destination. If you then try to print that string or use strlen on it, the program will keep reading past your buffer into random memory until it happens to find a zero byte. Always manually null-terminate the last index of your buffer when using strncpy to be safe.
📋 Practical Task
Implementing a Safe Player Name Sanitizer
You are writing a module for a game that handles player profiles. The system requires that player names be stored in a fixed-size buffer of 16 bytes. However, users often try to enter names that are far too long.
Write a program that does the following:
- Defines a destination buffer
char player_name[16]. - Takes a long input string (e.g.,
"Sir_Lancelot_The_Brave_and_Bold"). - Uses
strlento check if the input exceeds the buffer capacity. - If it is too long, it should use
strncpyto truncate the name to fit the buffer (leaving room for the null terminator) and manually ensure the string is null-terminated. - If it fits, it should copy the string normally.
- Prints the final stored name and its length using
strlento verify it was handled correctly.
There are no comments for now.