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)

UnsafeSafe alternativeKey difference
strcpystrncpy / snprintfLength-limited
strcatstrncat / snprintfLength-limited
getsfgetsBounded read
sprintfsnprintfBuffer size specified

gets is so dangerous it was removed from the C11 standard entirely. Never use it.

TL;DR

  • strlen excludes the null terminator — allocate strlen + 1 bytes
  • strcpy and strcat have no bounds checking — use snprintf instead
  • Use strcmp to compare strings, never ==
  • The return value of strcmp is 0 for equal, negative/positive for ordering
  • strstr returns 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