strlen in C – Why strlen(“hello”) Is 5, Not 4 or 6

How long is "hello"? Five letters — but C strings end with a hidden '\0', arrays are indexed from zero, and sizeof gives yet another number. This question from our C Programming Quiz App sorts out exactly which number strlen returns — and which off-by-one traps produce every wrong option.

The Quiz Question

char *p = "hello";
printf("%d", (int)strlen(p));

What is printed by this code?

  1. 4
  2. 5
  3. 6
  4. Compile error

The Correct Answer: 5

strlen walks the string from the first character and counts until it hits the null terminator — not including it. "hello" has five characters before the '\0', so the answer is 5. Verified on gcc 13.3 and Apple clang 21, clean under -ansi -Wall -Wextra:

$ gcc -ansi -Wall -Wextra len.c && ./a.out
strlen  = 5
sizeof "hello" = 6
sizeof(p) = 8

The three numbers in that output are the three ways to “measure” the same string — and each wrong quiz option comes from picking the wrong one.

Why Each Wrong Answer Is Wrong

Why not 4?

4 is the index of the last character (p[4] is 'o'), a zero-based-indexing reflex misapplied to length. Indices run 0–4; the count of characters is 5. Length and last-index always differ by one.

Why not 6?

6 counts the null terminator — that’s sizeof "hello", the storage the literal occupies. strlen is defined to stop at the terminator and exclude it. The two functions differ by exactly 1 for any string that exactly fills its array — the subject of the sizeof vs strlen question.

Why not a compile error?

With <string.h> included, everything is well-typed. One subtlety worth noticing: strlen returns size_t, not int — printing it with a bare %d would be a format mismatch. The quiz code does it right by casting: (int)strlen(p). (Without the cast, both gcc and clang warn under -Wall; the portable no-cast spelling is %zu.)

How strlen Actually Works

The classic implementation is a three-line loop:

size_t my_strlen(const char *s)
{
    const char *start = s;
    while (*s)
        s++;
    return (size_t)(s - start);
}

Two consequences follow directly. First, strlen is O(n) — it re-walks the string every call, which is why for (i = 0; i < strlen(s); i++) hides a quadratic loop; hoist the length into a variable. Second, the argument must be null-terminated — handed a buffer without a '\0', strlen marches through memory until it finds one, which is undefined behavior. (Real library versions read a word at a time with bit tricks, but the contract is the same — we’ve implemented strlen from scratch if you want to compare.)

Frequently Asked Questions

Does strlen count the null terminator?

No. It counts characters up to — but not including — the first '\0'. strlen("hello") is 5, while the literal occupies 6 bytes of storage.

What does strlen return — int or size_t?

size_t, an unsigned type. Print it with %zu, or cast to a matching type as this quiz code does with (int). A bare %d without a cast is a format mismatch that both gcc and clang warn about.

Is strlen expensive to call?

It’s O(n) — it walks the whole string every time. Calling it inside a loop condition re-measures the string on every iteration; store the result in a variable before the loop instead.

Related Reading

Recommended Books

This question is #110 in the C Programming Quiz App — 155 questions with explanations covering arrays, strings, pointers, and more.
Download on Google Play →

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>