Reimplementing strlen in C Using Pointer Subtraction
When transitioning from higher-level languages to C, strings can initially feel a bit mysterious. C doesn’t have a native, built-in string data type that automatically manages its own size. Instead, a string in C is simply a contiguous array of characters residing in memory, ending with a special null terminator character ('\0').
To find the length of a string, the standard library provides the strlen function. Reimplementing this function from first principles is a classic exercise that helps open the “black box” of memory management. While many beginners solve this using array indices and an integer counter, today we are going to look at a highly efficient, production-grade approach that relies entirely on pointer arithmetic and subtraction.
The Code
Here is the complete, working C program, complete with its expected console output:
#include <stdio.h>
int mystrlen(const char *input);
int main(void) {
char test1[] = "Hello";
char test2[] = "";
char test3[] = "C Programming";
printf("String length of %s is %d\n", test1, mystrlen(test1));
printf("String length of %s is %d\n", test2, mystrlen(test2));
printf("String length of %s is %d\n", test3, mystrlen(test3));
return 0;
}
int mystrlen(const char *input) {
const char *start = input;
while (*input != '\0') {
input++;
}
return (input - start);
}
/* * Program Output:
* String length of Hello is 5
* String length of is 0
* String length of C Programming is 13
*/
How It Works
Instead of incrementing an integer variable (like counter++) every time we see a character, this function relies entirely on navigating through memory addresses.
- Save the Start 📍: We store the memory address where the string begins in a pointer called
start. - Scan the String 🔍: The
while (*input != '\0')loop checks the character at the current address. If it is not the null terminator,input++increments the pointer itself, moving it to the very next byte in memory. - Subtract the Pointers 📐: Once the loop hits
'\0', theinputpointer stops moving. By subtracting the starting address from this final address (input - start), C automatically calculates exactly how many characters sit between those two points in memory.
Deep Dive: Values vs. Memory Addresses
When writing pointer-based code, a common trap involves understanding exactly what we are assigning to our tracking pointer. Let’s look at the critical difference between these two expressions:
The Incorrect Way: char *start = *input;
If we write this, the compiler will throw an error or warning. Why?
inputis a pointer holding a memory address (e.g.,0x7fff5fbff610).*input(with the asterisk) dereferences the pointer. It grabs the actual value stored at that address. For the string"Hello",*inputevaluates to the character'H'.- Writing
char *start = *input;attempts to take that character value'H'(which has an ASCII value of 72) and treat the number 72 as a raw memory address. This causes a dangerous type mismatch.
The Correct Way: const char *start = input;
- Here, we copy
inputdirectly without dereferencing it. - We are copying the raw memory address itself into
start. Now, both pointers point to the exact same location in memory (the beginning of the string). - We match the
constqualifier because the original string data is protected from modification.
What Happens with an Empty String?
This pointer subtraction logic handles edge cases beautifully. If we pass an empty string "" to mystrlen:
startis set to the memory address of the string.- The loop immediately checks
*input. Since the very first character of an empty string is'\0', the loop condition is false and it never runs. - The function returns
input - start. Sinceinputnever moved, both pointers hold the exact same address. The math becomesaddress - address, which cleanly returns0.