String Handling in Depth
C strings as char arrays: manipulation, safety, and common functions
Introduction
In this lesson, you'll learn about string handling in depth in C. Coming from JavaScript, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.
In JavaScript, you're familiar with c strings as char arrays: manipulation, safety, and common functions.
C has its own approach to c strings as char arrays: manipulation, safety, and common functions, which we'll explore step by step.
The C Way
Let's see how C handles this concept. Here's a typical example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void) {
char s[] = "Hello, World!"; // mutable copy
// Length
size_t len = strlen(s); // 13 — O(n), not a property!
// Comparison (never use ==)
if (strcmp(s, "Hello, World!") == 0) { /* equal */ }
strncmp(s, "Hello", 5); // compare first 5 chars
// Copy
char dst[50];
strcpy(dst, s); // unsafe if dst too small!
strncpy(dst, s, 49); // safer — limit chars
dst[49] = '\0'; // strncpy may not null-terminate!
// Concatenation
char buf[50] = "Hello, ";
strcat(buf, "Alice!"); // unsafe
strncat(buf, "Alice!", 49 - strlen(buf)); // safer
// Search
char *pos = strchr(s, 'W'); // pointer to first 'W'
char *sub = strstr(s, "World"); // pointer to "World"
// Formatted string
char msg[100];
snprintf(msg, sizeof(msg), "Value: %d", 42); // safe printf to buffer
// Duplicate (heap alloc)
char *copy = strdup(s); // must free()!
free(copy);
return 0;
}Comparing to JavaScript
Here's how you might have written similar code in JavaScript:
const s = "Hello, World!";
s.length; // 13
s.toUpperCase(); // "HELLO, WORLD!"
s.includes("World"); // true
s.indexOf("o"); // 4
s.slice(7, 12); // "World"
s.replace("World","C"); // "Hello, C!"
const parts = s.split(", "); // ["Hello","World!"]
// Concatenation
const greeting = "Hello, " + "Alice!";
// Formatting
const msg = `Value: ${42}`;You may be used to different syntax or behavior.
C strings are null-terminated char arrays — strlen() is O(n), not a property
You may be used to different syntax or behavior.
strcmp() for equality — never use == (compares pointers, not content)
You may be used to different syntax or behavior.
strcpy/strcat are unsafe; prefer strncpy/strncat/snprintf with size limits
You may be used to different syntax or behavior.
strdup() allocates a heap copy — must be freed with free()
You may be used to different syntax or behavior.
String literals ("hello") are read-only; char[] copies are mutable
Step-by-Step Breakdown
1. Strings are char Arrays
C strings are arrays of chars ending with a null byte '\0'. The string length is the number of chars before '\0'.
const s = "Hello"; s.length; // 5char s[] = "Hello"; // {'H','e','l','l','o','\0'}
size_t len = strlen(s); // 5 — counts to \02. Comparison and Search
Always use strcmp() to compare strings. == compares memory addresses, which will almost always differ even for identical content.
s === "hello"
s.includes("ell")
s.indexOf("l")strcmp(s, "hello") == 0 // equality
strstr(s, "ell") != NULL // contains
strchr(s, 'l') // first char3. Safe Copying and Formatting
Use snprintf instead of sprintf for safe formatted strings. Use strncat/strncpy with size checks to prevent buffer overflows.
const msg = `Value: ${n}`;char buf[100];
snprintf(buf, sizeof(buf), "Value: %d", n);
// sizeof(buf) limits output — never overflows4. strdup and Memory
strdup() creates a heap-allocated copy. It's convenient but requires a matching free(). Prefer stack buffers when size is known.
const copy = s.slice(); // GC handles memorychar *copy = strdup(original);
if (copy == NULL) { /* malloc failed */ }
// ... use copy ...
free(copy); // MUST free to avoid leakCommon Mistakes
When coming from JavaScript, developers often make these mistakes:
- C strings are null-terminated char arrays — strlen() is O(n), not a property
- strcmp() for equality — never use == (compares pointers, not content)
- strcpy/strcat are unsafe; prefer strncpy/strncat/snprintf with size limits
Key Takeaways
- strcmp() for equality; strstr()/strchr() for searching — never use == on strings
- snprintf(buf, sizeof(buf), fmt, ...) is the safe way to build strings
- strncpy/strncat with size limits prevent buffer overflows
- strdup() heap-allocates a copy — always free() it when done