sizeof of a String Array in C – Why “hi” Takes 3 Bytes

How big is the array behind the string "hi"? Two characters, so two bytes — right? This question from our C Programming Quiz App catches everyone who forgets that C strings carry an invisible passenger: the null terminator. sizeof sees it; your eyes don’t.

The Quiz Question

char str[] = "hi";
printf("%lu", sizeof(str));

What is printed by this code?

  1. 2
  2. 3
  3. 4
  4. 1

The Correct Answer: 3

When you initialize a char array from a string literal, the compiler sizes the array to hold every character plus the terminating '\0'. "hi" is 'h', 'i', '\0' — three bytes — so str is declared as char str[3] and sizeof(str) is 3. Verified on gcc 13.3 and Apple clang 21, clean under -Wall -Wextra:

$ gcc -Wall -Wextra size.c && ./a.out
sizeof(str) = 3
strlen(str) = 2
sizeof(p)   = 8

The extra two lines show the two classic confusions side by side: strlen counts only the visible characters (2), and sizeof applied to a pointer to the same string gives the pointer’s own size (8 on a 64-bit machine), not the string’s.

Why Each Wrong Answer Is Wrong

Why not 2?

2 is strlen(str) — the number of characters before the terminator. sizeof is a different beast: it reports the storage the object occupies, and the array was sized to store the terminator too. If you remember one line from this post: sizeof a string array = strlen + 1.

Why not 4?

There is no padding or alignment overhead inside a char array — sizeof(char) is 1 by definition, and array size is exactly element count × element size. The “round it up to 4” instinct comes from struct padding, which doesn’t apply here.

Why not 1?

1 would be sizeof(str[0]) — a single char. Applied to the whole array, sizeof gives the whole array’s size. (This distinction is also why sizeof(arr)/sizeof(arr[0]) is the standard idiom for element count.)

Array vs Pointer: Where sizeof Changes Its Answer

The same literal behaves very differently behind a pointer:

char str[] = "hi";   /* array: sizeof = 3 */
char *p   = "hi";    /* pointer: sizeof(p) = 8 (on 64-bit) */

The array is the storage; the pointer merely refers to storage that lives elsewhere. Pass either one to a function, though, and the array decays to a pointer — inside the function, sizeof can only ever see pointer size. That’s why functions that need a buffer’s size must receive it as a separate parameter, and why sizeof-based length tricks only work in the scope where the array was declared.

Frequently Asked Questions

Why is sizeof(“hi”) 3 and not 2?

A string literal always includes a terminating '\0'. The array initialized from "hi" holds 'h', 'i', and '\0' — three bytes.

What’s the difference between sizeof and strlen for strings?

sizeof reports the storage size of the object at compile time, including the null terminator (and unused tail space, if the array is bigger than the string). strlen walks the characters at run time and counts them up to — but not including — the first '\0'.

Why does sizeof give 8 for a char pointer to the same string?

Because it measures the pointer variable itself, not what it points to. All object pointers are 8 bytes on typical 64-bit platforms, regardless of how long the string is.

Related Reading

Recommended Books

This question is #19 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>