C Library Masterclass: strlen, strcpy, strcat, strcmp & Security

⚑ C (C17 / C23 Standard) 🟒 Lesson 19 πŸ“‚ Phase 08: Strings & Text Processing πŸ“… 2026 Comprehensive Master Edition
πŸ“Œ Covered in this in-depth guide: strlen() Complexity Β· strcpy vs strncpy Β· strcat vs strncat Β· strcmp & strncmp Β· strchr & strstr Β· Buffer Overflow CVEs Β· Manual Reimplementations

Welcome to Phase 8 (Chapter 19): C <string.h> Standard Library & Buffer Overflow Security Masterclass! Because C does not treat strings as high-level objects with built-in methods, all string operationsβ€”from finding lengths to copying, concatenating, comparing, and searching substringsβ€”are executed via the standard <string.h> library header. In this exhaustive guide, you will master the internal algorithms, time complexities, and hardware memory movements of core string functions, analyze why unbounded functions like strcpy() caused historical cyber exploits, learn how to use bounded safe variants (strncpy, strncat, strncmp), and construct clean manual pointer-based reimplementations from scratch.

1The Standard <string.h> Library Function Matrix

The C standard library categorizes string functions into 5 core families: Measurement, Copying, Concatenation, Comparison, and Searching:

Function SignatureRole & MechanismTime ComplexitySecurity Status
size_t strlen(const char* s) Scans memory sequentially counting characters until '\0'. $O(N)$ (Linear Scan) βœ… Safe (Read-Only)
char* strcpy(char* dest, const char* src) Copies all characters from src to dest including '\0'. $O(N)$ ⚠️ UNSAFE! No buffer limit.
char* strncpy(char* dest, const char* src, size_t n) Copies at most $n$ characters. ⚠️ Does not null-terminate if $n \le \text{len}$! $O(n)$ βœ… Bounded (Needs manual '\0')
char* strcat(char* dest, const char* src) Finds end of dest and appends src. $O(\text{len}_1 + \text{len}_2)$ ⚠️ UNSAFE! Potential overflow.
char* strncat(char* dest, const char* src, size_t n) Appends at most $n$ chars and always appends '\0'. $O(\text{len}_1 + n)$ βœ… Bounded & Safe
int strcmp(const char* s1, const char* s2) Lexicographical ASCII subtraction ($s_1[i] - s_2[i]$). Returns 0 if equal. $O(N)$ βœ… Safe (Read-Only)
char* strchr(const char* s, int c) Returns pointer to first occurrence of character $c$, or NULL. $O(N)$ βœ… Safe
char* strstr(const char* haystack, const char* needle) Returns pointer to first occurrence of substring needle in haystack. $O(N \times M)$ βœ… Safe
2strlen() vs sizeof() Deep Architectural Comparison

⚑ strlen() vs sizeof() in Depth:

β€’ sizeof(str): Evaluates the Total Physical RAM Buffer Size in Bytes allocated at compile time (an $O(1)$ constant value).
β€’ strlen(str): Traverses RAM at runtime counting characters until it hits '\0' (an $O(N)$ dynamic operation that excludes the null terminator!).

Example: For char name[50] = "Dennis";:
- sizeof(name) = 50 Bytes (Total Stack buffer).
- strlen(name) = 6 Characters (Actual payload text length).

3Safe Bounded String Copying & Concatenation

To prevent buffer overflows in production code, always use bounded variants and guarantee null termination:

C β€” Safe String Manipulation Architecture β–Ά Run Code in C Compiler
#include <stdio.h>
#include <string.h>

int main(void) {
    char source[] = "Operating Systems";
    char destination[30];

    // 1. Safe Bounded Copy with strncpy
    strncpy(destination, source, sizeof(destination) - 1);
    destination[sizeof(destination) - 1] = '\0'; // Explicit Null-Terminator Safety Guarantee!

    // 2. Safe Bounded Concatenation with strncat
    strncat(destination, " in C", sizeof(destination) - strlen(destination) - 1);

    printf("Result String: %s\n", destination);
    printf("Total Length: %zu chars | Buffer Capacity: %zu bytes\n", strlen(destination), sizeof(destination));

    // 3. Substring Search with strstr
    char* found = strstr(destination, "Systems");
    if (found != NULL) {
        printf("Substring 'Systems' found starting at index: %ld\n", found - destination);
    }

    return 0;
}
4Manual Pointer-Based Reimplementation of <string.h>

Understanding how standard library functions operate under the hood using raw pointer arithmetic is an essential skill for system software engineers:

πŸ› οΈ Recreating Core C String Functions From Scratch:

1. Custom my_strlen:
size_t my_strlen(const char* s) { const char* p = s; while (*p) p++; return p - s; }

2. Custom my_strcpy (The Classic Dennis Ritchie 1-Liner):
char* my_strcpy(char* dest, const char* src) { char* d = dest; while ((*d++ = *src++)); return dest; }

3. Custom my_strcmp:
int my_strcmp(const char* s1, const char* s2) { while (*s1 && (*s1 == *s2)) { s1++; s2++; } return *(const unsigned char*)s1 - *(const unsigned char*)s2; }

5Frequently Asked Questions & Technical Interview Deep-Dive

Q1: Why does strcmp("apple", "banana") return a negative number?

strcmp subtracts ASCII values at the first differing index. For index 0: 'a' (97) - 'b' (98) = -1. Because $-1 < 0$, it indicates that "apple" precedes "banana" in lexicographical order.

Q2: What is the critical pitfall of strncpy()?

If the source string length is greater than or equal to $n$, strncpy fills all $n$ characters WITHOUT appending a null terminator ('\0'). The destination buffer is left unterminated, causing memory leaks if printed.

Q3: Why must strcmp cast pointers to unsigned char before subtraction?

The C standard dictates that character comparisons must behave as if characters are unsigned. If plain char is signed by default on the target architecture, non-ASCII characters (values $ge 128$) could yield negative values incorrectly.

πŸ’» Try It Yourself β€” Test String Comparisons in Online C Compiler

Run this string comparison and search demo in our live GCC compiler:

C (GCC Standard) β–Ά Open C Compiler
#include <stdio.h>
#include <string.h>

int main(void) {
    char s1[] = "Linux";
    char s2[] = "Linux";
    printf("strcmp result: %d (0 means EXACT MATCH)\n", strcmp(s1, s2));
    return 0;
}
Open in Online C Compiler β†’