Arrays and sizeof
Store many values of one type in a row, start counting at zero, walk the array with a loop, and let sizeof tell you how many there are.
A row of values
An array is a fixed row of values of one type, held one after another. You write the type, the name, and the number of slots: int scores[5]; is room for five whole numbers.
You can fill it as you declare it: int scores[5] = {90, 75, 82, 60, 99};. The values sit in the array in the order you wrote them, and the count must not be larger than the room you asked for.
Counting from zero
The first slot is position zero, not one, so an array of five slots runs from zero to four. scores[0] is the first value and scores[4] is the last. That off by one is the doorway to most array bugs.
A loop pairs naturally with an array: one counter from zero up to the number of slots, reading scores[i] each pass. The loop walk is how you add, search, or print every value.
How many slots
You can ask an array its size with sizeof. sizeof(scores) is the whole array in bytes, and sizeof(scores[0]) is one slot in bytes. Dividing one by the other gives the number of slots.
That trick keeps a loop honest when you later change the size: write the count once and everywhere that needs it reads the same value. It is the standard C way to stop hard coding a number that will move.
One block, fixed stride
An array's slots sit next to each other in memory, each the same number of bytes apart. scores[2] is not a lookup by name; it is the start address plus two slot widths. That is why the index must be a whole number, and why the first index is zero.
The compiler knows the slot width from the type, so an int array and a double array step differently. It does not know how many slots you meant to allocate; that count exists only in your head and in the loop bound.
sizeof, and where it stops working
sizeof(scores) works only where the array itself is visible. Pass scores to a function and what arrives is a pointer to the first slot; sizeof there is the size of a pointer, not of the array. Pass the count as a second argument.
A partial initialiser fills the rest with zeros: int counts[5] = {1, 2}; leaves three zeros. A local array declared without an initialiser gets no such treatment — its slots hold whatever was there before, so read them only after you write them.
Copying a row of values
An array name is not a value you can assign. int copy[5] = scores; does not compile, and copy = scores is rejected too, because an array in an expression turns into a pointer to its first slot. To copy the contents you have to move them: a loop from zero to the count, or memcpy from <string.h> with the byte count.
The same rule explains why a function cannot return an array. It can return a pointer, but the array that pointer names has to outlive the call, which is why callers pass the destination in or the function allocates it. The chapter on dynamic memory is where that second option lives.
Two dimensions, one block
int grid[3][4] is three rows of four ints, and the rows sit one after another in memory. The first index chooses the row, the second chooses the column inside it. sizeof(grid) is the whole block, sizeof(grid[0]) is one row, and sizeof(grid[0][0]) is one int.
Nested loops visit it in the order the memory is laid out: the outer loop walks rows, the inner loop walks columns. Swapping them still visits every cell, but the access pattern jumps around the block, which matters once the grid is large enough for the cache to notice.
Three array mistakes are worth watching for: a loop bound of i <= count, which reads one slot past the end; sizeof on a parameter, which measures a pointer; and reading slots you never filled. The first is undefined behaviour, the second silently gives the wrong count, and the third prints whatever memory happened to hold.
Try these next
- Change the initialiser to
{90, 75}and print all five slots; the last three should read zero. - Write a loop that finds the smallest value and the index where it sits.
- Pass the array to a function with its count, print the total there, and try
sizeofinside the function to see what it measures.
Declare and walk
#include <stdio.h>
int main(void) {
int nums[3] = {4, 8, 15};
int i;
for (i = 0; i < 3; i++) {
printf("%d\n", nums[i]);
}
return 0;
}Sum an array
Run it to see the count, the total and the ends of the array. Then add a sixth score and let sizeof update the loop for you.
Find the largest, and where it lives
Run it, then change every score to a negative number and check that the best is still found. Change the starting value to zero and see the bug it causes.
Reading or writing past the last slot does not stop your program with a clear message — it quietly corrupts memory nearby. Keep the loop bound at the number of slots and no more.
Check what you learned
One question at a time. A wrong answer explains itself — take another go.
Part 1 of 5
What is the index of the first slot in a C array?
