Understanding how to determine the size of a character array is a fundamental skill for anyone working with the C programming language. So unlike higher-level languages that store length metadata alongside the string data, C treats strings as simple arrays of characters terminated by a specific marker. This design choice places the responsibility of calculation squarely on the developer, making it essential to master the standard library functions, manual iteration techniques, and the critical distinction between logical length and allocated memory size Less friction, more output..
The Anatomy of a C String
Before diving into the methods for calculating size, it is vital to understand what a string actually is in C. This leads to a string is a contiguous sequence of characters stored in memory, ending with a null terminator, represented as '\0' (ASCII value 0). This sentinel value is the only way standard library functions know where the string ends Simple, but easy to overlook. Turns out it matters..
Consider the declaration char str[] = "Hello";. Even so, in memory, this occupies six bytes: H, e, l, l, o, and '\0'. The logical length—the number of printable characters—is 5. The storage size is 6. Confusing these two concepts is a primary source of buffer overflows and off-by-one errors in C programming And that's really what it comes down to..
Using the Standard Library: strlen
The most common and idiomatic way to find the length of a string is the strlen function, defined in the <string.h> header. It returns a value of type size_t, an unsigned integer type capable of representing the size of the largest possible object on the target platform Simple as that..
Syntax and Behavior
#include
size_t strlen(const char *str);
The function accepts a pointer to the first character of the string. Now, it iterates through memory starting at that address, incrementing a counter until it encounters the null terminator. Crucially, the return value does not count the null terminator.
Practical Example
#include
#include
int main() {
char message[] = "C Programming";
size_t len = strlen(message);
printf("The string is: %s\n", message);
printf("Length (excluding null terminator): %zu\n", len);
// Output: Length (excluding null terminator): 13
return 0;
}
Performance Considerations
strlen has a time complexity of O(n), where n is the length of the string. Practically speaking, because it must scan every character sequentially, calling strlen repeatedly inside a loop condition—such as for (i = 0; i < strlen(s); i++)—results in O(n²) complexity. This is a classic performance anti-pattern. Always cache the result in a variable before the loop if the string does not change.
Counterintuitive, but true.
Safety Constraints
strlen relies entirely on the presence of a valid null terminator. If the character array is not null-terminated (perhaps due to a buffer overflow, manual memory manipulation, or reading raw binary data), strlen will continue reading past the intended buffer boundaries until it randomly encounters a zero byte in memory. Worth adding: this leads to Undefined Behavior (UB), often resulting in segmentation faults or incorrect length calculations. Never use strlen on untrusted or potentially non-null-terminated buffers.
Manual Calculation: The Pointer Arithmetic Approach
Writing a custom length function is a rite of passage for C programmers and an excellent way to understand pointer arithmetic. Since an array name decays to a pointer to its first element, we can traverse the string by incrementing the pointer address Simple, but easy to overlook..
Implementation Using a While Loop
size_t my_strlen(const char *str) {
const char *ptr = str;
// Advance pointer until null terminator is found
while (*ptr != '\0') {
ptr++;
}
// The difference between final and initial address is the length
return (size_t)(ptr - str);
}
Implementation Using a For Loop
A more compact version often seen in kernel code or embedded systems:
size_t my_strlen(const char *str) {
const char *s;
for (s = str; *s; ++s);
return (s - str);
}
In this snippet, the loop condition *s evaluates to false (0) only when the null terminator is reached. The expression s - str performs pointer subtraction, yielding the number of elements (bytes) between the two addresses. This is defined behavior in C only when both pointers point into the same array object (or one past the end) But it adds up..
Why Use a Custom Function?
While strlen is highly optimized (often using SIMD instructions or word-aligned reads to check 4, 8, or 16 bytes at a time), a manual implementation is useful for:
- Educational purposes: Demonstrating pointer mechanics.
- Constrained environments: Systems where linking the standard library is undesirable.
- Custom sentinels: Modifying the logic to stop at a different character (e.On the flip side, g. , newline
\nor space) without creating a temporary null-terminated copy.
The sizeof Operator Trap
A pervasive mistake among beginners is using the sizeof operator to find string length.
char buffer[100] = "Hello";
printf("%zu\n", sizeof(buffer)); // Prints 100 (size of array)
printf("%zu\n", sizeof("Hello")); // Prints 6 (size of literal including \0)
sizeof is a compile-time operator (mostly) that returns the size of the type or variable in bytes, not the runtime length of the data contained within.
- Applied to an array: Returns the total allocated size (capacity), not the current content length.
- Applied to a pointer: Returns the size of the pointer itself (4 bytes on 32-bit, 8 bytes on 64-bit), which is almost never what you want.
- Applied to a string literal: Returns the static size including the null terminator.
Use sizeof only when you need the buffer capacity (e.g., for fgets(buffer, sizeof(buffer), stdin)), never for the logical string length Worth knowing..
Handling Wide Characters and Multibyte Strings
Standard strlen counts bytes, not characters. This distinction is critical when dealing with character encodings like UTF-8, where a single visual character (grapheme cluster or code point) may occupy 2, 3, or 4 bytes.
Wide Characters (wchar_t)
For wide strings (typically UTF-16 or UTF-32 depending on the platform), use wcslen from <wchar.h> Most people skip this — try not to..
#include
#include
int main() {
wchar_t *ws = L"Hello 世界"; // 2 ASCII + 2 Wide chars
size_t len = wcslen(ws); // Returns 4 (number of wchar_t elements)
// Note: sizeof(wchar_t) is 2 on Windows (UTF-16), 4 on Linux (UTF-32)
return 0;
}
The official docs gloss over this. That's a mistake Less friction, more output..
Multibyte Strings (UTF-8)
Counting actual Unicode code points in a UTF-8 char* string requires parsing the byte sequences. The standard library provides mbstowcs (multibyte string to wide character string) for conversion, or you can iterate manually checking the leading bits of each byte Simple, but easy to overlook..
// Simplified UTF-8 code point counter (does not validate fully)
size_t utf8_strlen(const char *str) {
size_t count = 0;
while (*str) {
// Check if byte is a leading byte (not a continuation byte 10xxxxxx)
if ((*str & 0xC0) != 0x80) {
count++;