You gave the array five slots but only two values. What lives in slot three — leftover memory garbage, or something the language guarantees? This question from our C Programming Quiz App tests one of C’s most useful (and most doubted) rules: a partial initializer zero-fills everything you didn’t mention.
The Quiz Question
int a[5] = {1, 2};
printf("%d", a[3]);
What is printed by this code?
- A garbage value
- 0
- 2
- Compile error
The Correct Answer: 0
When an initializer list is shorter than the array, the remaining elements are initialized as if they had static storage duration — which for int means zero. a[0] and a[1] get 1 and 2; a[2], a[3], a[4] are all guaranteed 0. This rule has been in the language since C89 (C99 6.7.8p21). Verified on gcc 13.3 and Apple clang 21, clean under -ansi -Wall -Wextra:
$ gcc -ansi -Wall -Wextra partial.c && ./a.out a[0] = 1 a[1] = 2 a[2] = 0 a[3] = 0 a[4] = 0
Why Each Wrong Answer Is Wrong
Why not a garbage value?
Garbage is what you get with no initializer at all. A local int a[5]; without = {...} really is indeterminate — we ran that version too:
int a[5]; /* no initializer */
$ ./a.out (gcc 13.3, Linux x86-64) a[0] = 0 a[1] = 0 a[2] = 21379824 a[3] = 32395 a[4] = -1091445360 $ ./a.out (Apple clang 21, ARM64) a[0] = -1 a[1] = 1830267064 a[2] = 1 a[3] = -101089024 a[4] = 1
Different machine, different garbage — gcc even flags it with -Wmaybe-uninitialized. But the moment you write any initializer, even {0} or {1}, the “rest are zero” guarantee kicks in. The presence of the braces is what flips the behavior.
Why not 2?
C does not repeat the last initializer to fill the array — that’s a feature of some other languages’ idioms, not C’s. Element 1 gets the 2; elements 2 through 4 get zero, not a copy of 2.
Why not a compile error?
A shorter-than-array initializer list is perfectly legal (the reverse — more initializers than elements — is the error). Both compilers accept it silently with all warnings enabled.
The Idiom This Enables: = {0}
The zero-fill rule is why this classic one-liner works:
int counts[256] = {0}; /* all 256 elements are 0 */
The explicit 0 initializes element 0; the rule zero-fills the other 255. The same applies to structs (struct point p = {0}; zeroes every member) and it’s the standard way to get a cleanly zeroed local aggregate without memset. One caveat for readability: {0} zero-fills, but so does {5} — it sets element 0 to 5 and the rest to zero, which surprises people who expect all-fives.
Frequently Asked Questions
Are unlisted array elements guaranteed to be zero in C?
Yes — if the array has an initializer list at all. Elements not covered by the list are initialized like static objects: arithmetic types to zero, pointers to NULL. With no initializer, a local array is indeterminate (garbage).
Does int a[5] = {0} zero the whole array?
Yes. The 0 initializes a[0] and the partial-initializer rule zeroes a[1] through a[4]. It’s the idiomatic way to zero a local array at declaration.
What happens if the initializer list is longer than the array?
That’s a constraint violation — int a[2] = {1, 2, 3}; does not compile. Shorter lists are legal; longer ones are not.
Related Reading
- sizeof of a String Array in C – Why “hi” Takes 3 Bytes
- C Program to Find the Size of an Array
- C Program to Insert an Element into an Array
- C Aptitude Questions and Answers
Recommended Books
- The C Programming Language – Kernighan & Ritchie (India) | Amazon.com
- C Programming: A Modern Approach – K.N. King (India) | Amazon.com
This question is #22 in the C Programming Quiz App — 155 questions with explanations covering arrays, strings, pointers, and more.
Download on Google Play →