Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.
C Array Output Questions
Learn to predict the output of tricky array programs: sentinel loops, pre-decrement in subscripts, array size inside functions and more.
C array output questions are a favourite in college exams, written tests and embedded interviews because they expose whether you truly understand how arrays behave in memory. In this lecture of our free C programming course you will learn a repeatable method for predicting the output of array programs, and you will study five classic traps with original, tested examples. These traps cause real bugs in embedded C programming, so treat them as survival skills and not just exam tricks.
Topics Covered
What You Will Learn
- A four-step method to predict the output of any array program on paper.
- How a zero acts as a sentinel and stops a
while(arr[i])loop. - Why a pre-decrement inside a subscript changes both the index and the element.
- Why
sizeofgives a different answer inside a function than in the caller. - How a function can silently modify the caller’s array.
- Why variable-length arrays and off-by-one reads are dangerous in embedded code.
Prerequisites
- One-dimensional arrays: declaration, initialisation and indexing.
- Increment and decrement operators, prefix and postfix.
- Passing an array to a function.
- Basic
printfformat specifiers, including%dand%zu.
A Four-Step Method for C Array Output Questions
Never guess the output. Follow the same routine every time and most questions become mechanical.
Step 4 is the one that separates strong programmers from average ones. If an index can leave the valid range, the program has undefined behaviour and there is no single correct output. In an exam you should say so, and in a real project you should fix it.
Trap 1: The Zero Sentinel Loop
A while(data[i]) loop runs while the element is non-zero, so the first zero element ends it, even if more data follows. Consider this array and trace the loop.
int data[7] = {3, 8, 1, 0, 9, 4, 2};
int i = 0, total = 0;
while (data[i]) {
total += data[i];
i++;
}
| Iteration | i | data[i] | Condition | total after |
|---|---|---|---|---|
| 1 | 0 | 3 | true | 3 |
| 2 | 1 | 8 | true | 11 |
| 3 | 2 | 1 | true | 12 |
| 4 | 3 | 0 | false, loop ends | 12 |
The elements 9, 4 and 2 are never added. This pattern is legitimate when zero really means end of data, which is exactly how C strings work with the null terminator. It is a bug when zero is a valid reading, for example a sensor value of 0.
Trap 2: Pre-Decrement Inside the Subscript
An expression such as --v[--i] performs two decrements. The inner one changes the index variable first, and the outer one changes the array element found at the new index. Both changes are permanent.
int v[5] = {10, 20, 30, 40, 50};
int i = 4;
printf("%d\n", --v[--i]);
| Index | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| Before | 10 | 20 | 30 | 40 | 50 |
| After | 10 | 20 | 30 | 39 | 50 |
First --i turns 4 into 3. Then --v[3] turns 40 into 39 and yields 39 as the printed value. Afterwards i is 3, not 4.
--k inside a subscript, the counter moves two steps per round. With a condition that permits zero, the body can compute index -1 and read memory before the array. Always make the loop condition strict enough, for example k > 0, when the body consumes the counter this way.Here is a safe version that prints every second element from the end of an eight-element array:
int seq[8] = {1, 2, 3, 4, 5, 6, 7, 8};
for (int k = 7; k > 0; k--)
printf("%d ", seq[--k]);
The values printed are 7, 5, 3 and 1, because k visits 7, 5, 3 and 1 at the loop test and the body lowers it to 6, 4, 2 and 0 before indexing.
Trap 3: sizeof Inside and Outside a Function
In the function that owns the array, sizeof(data) returns the total number of bytes. When the array is passed to another function, what arrives is only the address of the first element, so the parameter behaves like a pointer. Writing int arr[] in the parameter list does not change that. The compiler therefore reports the size of a pointer, which is 8 bytes on a 64-bit PC and 4 bytes on a 32-bit Cortex-M. GCC warns about this with -Wsizeof-array-argument.
sizeof(data) / sizeof(data[0]).Trap 4: Functions Can Change Your Array
Because only an address is passed, a function that writes to its array parameter changes the original array in the caller. There is no copy. This is useful for in-place sorting and dangerous when you did not intend it. If a function only needs to read, declare the parameter const int arr[] so the compiler rejects accidental writes.
Run All Four Traps in One Program
The program below contains every example from the traps above. Compile it and compare your paper predictions with the real output.
#include <stdio.h>
#define SAMPLES 7
static void report_size(int arr[], int count)
{
printf("inside: sizeof(arr) = %zu, count = %d\n", sizeof(arr), count);
}
static void zero_first(int arr[])
{
arr[0] = 0;
}
int main(void)
{
int data[SAMPLES] = {3, 8, 1, 0, 9, 4, 2};
int v[5] = {10, 20, 30, 40, 50};
int seq[8] = {1, 2, 3, 4, 5, 6, 7, 8};
int i = 0, total = 0;
/* Trap 1: a zero ends a sentinel-controlled loop */
while (data[i]) {
total += data[i];
i++;
}
printf("stopped at index %d, total = %d\n", i, total);
/* Trap 2: pre-decrement inside a subscript */
i = 4;
printf("value printed = %d\n", --v[--i]);
printf("now i = %d, v[3] = %d\n", i, v[3]);
printf("every second element:");
for (int k = 7; k > 0; k--)
printf(" %d", seq[--k]);
putchar('\n');
/* Trap 3: array size inside and outside a function */
printf("outside: sizeof(data) = %zu bytes, %zu elements\n",
sizeof(data), sizeof(data) / sizeof(data[0]));
report_size(data, SAMPLES);
/* Trap 4: a function changes the caller's array */
zero_first(data);
printf("data[0] after zero_first = %d\n", data[0]);
return 0;
}
gcc -std=c11 -Wall -Wextra -o array_traps array_traps.c
./array_traps
Expected output on a 64-bit Linux machine (the compiler also prints the sizeof warning mentioned above):
stopped at index 3, total = 12
value printed = 39
now i = 3, v[3] = 39
every second element: 7 5 3 1
outside: sizeof(data) = 28 bytes, 7 elements
inside: sizeof(arr) = 8, count = 7
data[0] after zero_first = 0
Trap 5: Variable-Length Arrays and Off-by-One Reads
Two more patterns appear constantly in exam questions. The first is declaring an array with a size taken from a variable, as in int size = 5; int arr[size];. This is a variable-length array. It is legal in C99 and optional in C11, but it was not part of C89 and many embedded coding standards forbid it because the stack usage is not known at compile time. Prefer a constant such as #define COUNT 5.
The second is reading one element past the end. If an array has four elements, valid indices are 0 to 3. A loop that starts its counter at 4 and reads arr[i] before decrementing touches memory that belongs to something else. The program may print a stable-looking number, crash, or behave differently after a harmless edit elsewhere. That is the nature of undefined behaviour, and it is why you can never state a single correct output for such code.
| Pattern | Result | Safe alternative |
|---|---|---|
Read arr[size] | Undefined behaviour | Valid indices end at size - 1 |
int arr[n] with variable n | VLA, risky on small stacks | Constant size via #define or enum |
sizeof(arr) in a callee | Pointer size | Pass the count as a parameter |
| Zero as end marker | Stops early on real zeros | Use an explicit count |
Common Mistakes and Troubleshooting
- Forgetting that the callee sees a pointer: any count derived with sizeof in the callee will be wrong.
- Assuming side effects are temporary: a prefix or postfix operator changes the variable for good.
- Mixing two modifications of one variable in a single expression: for example using
i++andiin the same statement leads to undefined behaviour. Split the statement. - Trusting a lucky output: run suspicious code with
-fsanitize=address,undefinedto catch out-of-range accesses.
Best Practices, Performance and Security
- Keep one statement doing one job. Clear code is easier to trace and to review.
- Pass array length explicitly, and prefer
size_tfor counts. - Mark read-only parameters
const. - Out-of-range reads and writes are a leading cause of security vulnerabilities, so validate every index that comes from outside the program.
- Avoid variable-length arrays on microcontrollers where stack space is measured in kilobytes.
Summary
- Use the four-step paper method and always check index ranges.
- A zero sentinel ends a loop at the first zero, not at the last element.
- Prefix operators inside subscripts change both the index and the element.
- Inside a function an array parameter is a pointer, so sizeof returns the pointer size.
- Functions modify the caller’s array because no copy is made.
Whenever you meet new C array output questions, return to the four-step method and the five traps, because nearly every exam variation is a disguised version of one of them. With these five traps in your toolbox you can reason about almost any array output question and avoid the same mistakes in real firmware. The next lecture continues with multidimensional sizes, swapping, the sieve of Eratosthenes and stable partitioning.
FAQ: C Array Output Questions
How do I solve C array output questions quickly?
Draw the array with indices, track every variable, execute one statement at a time and finally check that each index stays within range.
Why does sizeof give a different value inside a function?
The array decays to a pointer to its first element when passed, so sizeof measures the pointer instead of the whole array.
What happens when I read arr[size]?
It is undefined behaviour. The program might print garbage, crash or appear to work, and the result can change between builds.
Is int arr[n] with a variable n allowed?
It is a variable-length array. C99 allows it and C11 makes support optional. Many embedded standards ban it, so use a constant size.
Can a function change my array?
Yes. The function receives the address of the first element, so any write goes straight to the original array. Use const for read-only access.
Why is the loop with –k inside the subscript safe only with k greater than 0?
The body lowers k again before indexing, so a condition that allows 0 would compute index -1.
Keep Going With the Free C Programming Course
Every lecture in this free C tutorial for embedded systems is original, tested and written for beginners who want real embedded C programming skills. Move on to the next lecture or return to the course index.
Need Help or More Information?
Questions about this free C programming course, embedded C training or career guidance? Get in touch.

2 Comments