C strings are null-terminated character arrays. The standard library provides functions to work with them, but every one of them has a failure mode that causes buffer overflows, incorrect results, or undefined behaviour. Here is what each function actually does and how to use it safely.
strlen — String Length
#include <stdio.h>
#include <string.h>
int main() {
char *str = "hello";
printf("length: %zun", strlen(str)); /* 5 — NOT 6 */
char arr[] = "hello";
printf("sizeof: %zun", sizeof(arr)); /* 6 — includes null terminator */
return 0;
}strlen returns the number of characters before the null terminator. sizeof on a char array includes the null terminator. This distinction matters whenever you allocate space for a string — always allocate strlen(str) + 1 bytes.
/* WRONG — one byte short, no room for */
char *copy = malloc(strlen(original));
/* CORRECT */
char *copy = malloc(strlen(original) + 1);strcpy — Copy a String
char dest[10];
char *src = "hello";
strcpy(dest, src); /* copies "hello" into dest */
printf("%sn", dest); /* hello */strcpy copies characters including the null terminator. It performs no bounds checking. If src is longer than dest can hold, it writes past the end of the buffer — a classic stack overflow vulnerability.
char dest[5];
strcpy(dest, "hello world"); /* writes 12 bytes into a 5-byte buffer — overflow */Use strncpy to limit the copy, or better, snprintf:
char dest[10];
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = ''; /* strncpy does not guarantee null termination */
/* Or cleaner: */
snprintf(dest, sizeof(dest), "%s", src); /* always null-terminates */strcat — Concatenate Strings
char buf[20] = "Hello";
strcat(buf, ", world"); /* appends ", world" to buf */
printf("%sn", buf); /* Hello, world */Like strcpy, strcat has no bounds checking. It scans to the end of buf (O(n)), then appends — meaning repeated strcat in a loop is O(n²). Use strncat to limit, or build strings with snprintf:
/* Safe concatenation using snprintf */
char result[64];
snprintf(result, sizeof(result), "%s%s", part1, part2);strcmp — Compare Strings
#include <string.h>
#include <stdio.h>
int main() {
char *a = "apple";
char *b = "banana";
int r = strcmp(a, b);
if (r == 0) printf("equaln");
else if (r < 0) printf("a comes firstn");
else printf("b comes firstn");
return 0;
}strcmp returns 0 if equal, a negative value if a < b lexicographically, and a positive value if a > b. The exact non-zero values are implementation-defined — only the sign matters.
The mistake: comparing with == instead of strcmp
char *s = "hello";
if (s == "hello") { /* WRONG — compares pointer addresses, not content */
printf("matchn");
}
if (strcmp(s, "hello") == 0) { /* CORRECT */
printf("matchn");
}This is directly related to how char* and char[] differ — == on pointers compares addresses, not the strings they point to. If you are getting no match even for equal-looking strings, this is the most likely cause.
Use strncmp to compare only the first N characters:
strncmp(a, b, 3); /* compares first 3 characters only */strstr — Find a Substring
#include <string.h>
#include <stdio.h>
int main() {
char *haystack = "the quick brown fox";
char *needle = "brown";
char *pos = strstr(haystack, needle);
if (pos) {
printf("Found at index %ldn", pos - haystack); /* 10 */
} else {
printf("Not foundn");
}
return 0;
}strstr returns a pointer to the first occurrence of needle in haystack, or NULL if not found. Subtract the two pointers to get the index.
Safe String Functions (C11 / POSIX)
| Unsafe | Safe alternative | Key difference |
|---|---|---|
strcpy | strncpy / snprintf | Length-limited |
strcat | strncat / snprintf | Length-limited |
gets | fgets | Bounded read |
sprintf | snprintf | Buffer size specified |
gets is so dangerous it was removed from the C11 standard entirely. Never use it.
TL;DR
strlenexcludes the null terminator — allocatestrlen + 1bytesstrcpyandstrcathave no bounds checking — usesnprintfinstead- Use
strcmpto compare strings, never== - The return value of
strcmpis 0 for equal, negative/positive for ordering strstrreturns a pointer to the found substring, not an index- Never use
gets— it was removed from C11 - Verify all string function behaviour in our c program compiler — paste any example and run it