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
96: String Concatenation: strcat, strncat
A few years back, I was reviewing code for a junior dev who was building a simple file-naming utility. He had a buffer for the filename and was using strcat to append a .log extension to the end of whatever the user provided. It worked perfectly during his initial tests. But the moment a user entered a long filename that pushed the total length right to the edge of the buffer, the program didn't just crash—it started overwriting other variables on the stack. He spent two days chasing a "ghost" bug where a completely unrelated integer variable was changing its value randomly. The culprit? He'd written past the end of his array because strcat doesn't know how big your buffer is; it just keeps writing until it hits the null terminator of the source string.
The Danger of the Blind Append
In C, strcat (string concatenate) is the most straightforward way to glue two strings together. It looks for the null terminator \0 at the end of your destination string and starts copying the source string right there. While it feels intuitive, it's essentially a "blind" operation. The function assumes you've allocated enough memory in the destination buffer to hold both the original string and the new one, plus the final null terminator.
char greeting[20] = "Hello, ";
char name[] = "Christopher";
strcat(greeting, name);
// greeting now contains "Hello, Christopher"
In the example above, we're safe because 20 bytes is plenty. But if name had been "Christopher-Alexander-the-Great", we would have marched right past the end of the greeting array and into memory we didn't own. This is a classic buffer overflow. I've seen this vulnerability used in countless security exploits; it's why you'll often hear senior devs groan when they see strcat in a pull request.
Capping the Growth with strncat
To avoid the disaster I mentioned, we use strncat. The "n" stands for a limit. This version of the function takes a third argument: the maximum number of characters to append from the source. It's a massive improvement, but there's a subtle trap here that trips up almost everyone at first.
The n parameter is not the total size of the buffer. It is the maximum number of characters to take from the source string. You still have to calculate how much room is actually left in your destination buffer.
char buffer[32] = "Log entry: ";
char message[] = "System failure detected in sector 7G";
int current_len = strlen(buffer);
int space_left = sizeof(buffer) - current_len - 1; // Leave room for \0
strncat(buffer, message, space_left);
Notice that subtraction of 1? That's the most important part of the math. strncat will always append a null terminator after the characters it copies. If you tell it to copy exactly as many characters as there are bytes left in the array, it will write the null terminator one byte past the end of your array. I've spent more hours than I'd like to admit debugging "off-by-one" errors exactly like this. Always leave that one byte of breathing room.
📋 Practical Task
Build a Safe Full-Path Generator
Write a program that constructs a full file path by concatenating a directory string and a filename string. You must ensure that the program never overflows the destination buffer, regardless of how long the input strings are.
- Define a destination buffer
char full_path[100]. - Initialize it with a directory path, e.g.,
"/usr/local/bin/". - Create a second string for a filename, e.g.,
"my_custom_script.sh". - Use
strncatto append the filename to the path. - You must calculate the remaining space dynamically using
strlenandsizeofto ensure the null terminator is safely placed within the 100-byte limit. - Print the final result to the console.
There are no comments for now.