Arrays are one of the first data structures you meet in C, and they matter because C gives you direct control over memory. That control is powerful, but it also means arrays do not come with guard rails. If you understand the basics early, you avoid a long list of bugs later: off-by-one mistakes, out-of-bounds access, wrong loop bounds, and confusion about how arrays behave when passed to functions.
This guide walks through the practical parts of arrays in C. You will see how to declare them, initialize them, read and write elements, loop through them, pass them to functions, and avoid common mistakes. The goal is not just to memorize syntax. The goal is to understand what the compiler is doing so you can use arrays confidently in real programs.
What an array is
An array is a fixed-size sequence of elements of the same type stored in contiguous memory. That means every item sits next to the next item in memory, which makes indexed access fast and predictable.
If you declare an array of five integers, you get five integer slots in a row. You access them with an index starting at 0, not 1. So the first element is numbers[0], the second is numbers[1], and the last element in a five-item array is numbers[4].
Why contiguous memory matters
Contiguous storage gives C arrays two useful properties:
- You can calculate the address of any element quickly.
- You can iterate through the entire array efficiently with a loop.
That same property also creates risk. If you go past the last valid index, C usually will not stop you. It may compile fine and fail later in a way that is hard to diagnose.
Declaring and initializing arrays
A basic array declaration looks like this:
int numbers[5];
That gives you room for five integers, but the values are uninitialized if the array is local. If you want to give it values immediately, you can initialize it:
int numbers[5] = {10, 20, 30, 40, 50};
You can also let the compiler infer the size from the initializer:
int numbers[] = {10, 20, 30, 40, 50};
That is often the cleanest option when you already know the full list of values.
Partial initialization
If you provide fewer values than the declared size, the remaining elements are set to zero:
int numbers[5] = {10, 20};
The array becomes {10, 20, 0, 0, 0}. This is useful when you want a larger buffer with only a few starting values.
Common declaration patterns
| Pattern | Example | Use case |
|---|---|---|
| Fixed size | int a[10]; | Buffer with known capacity |
| Full init | int a[3] = {1, 2, 3}; | Small list of known values |
| Size inferred | int a[] = {1, 2, 3}; | Convenient literal data |
| Char string | char name[] = "Ada"; | Text stored as a character array |
Accessing array elements
You read and write array values with square brackets:
int numbers[] = {10, 20, 30};
int first = numbers[0];
numbers[1] = 25;
The index must stay in range. For a three-element array, valid indices are 0, 1, and 2.
A safe mental model is this:
0is the first elementlength - 1is the last elementlengthis already too far
That last point is easy to miss. Many beginners accidentally write a loop like for (i = 0; i <= 5; i++) when they really need i < 5.
Looping through arrays
The most common way to use arrays is with a loop.
int main(void) {
int numbers[] = {4, 8, 15, 16, 23, 42};
int length = sizeof(numbers) / sizeof(numbers[0]);
for (int i = 0; i < length; i++) {
printf("%d
", numbers[i]);
}
return 0;
}
This example uses sizeof(numbers) / sizeof(numbers[0]) to calculate how many elements are in the array. That works only in the scope where numbers is an actual array, not when it has already been passed to a function as a pointer.
Why sizeof works here
sizeof(numbers) gives the total number of bytes used by the array. sizeof(numbers[0]) gives the size of one element. Dividing one by the other gives the element count.
This is a good pattern for local arrays, especially in examples, tests, and small programs.
Passing arrays to functions
When you pass an array to a function in C, it decays to a pointer to its first element. That means the function does not automatically know the length of the array.
#include <stdio.h>
void print_numbers(const int numbers[], int length) {
for (int i = 0; i < length; i++) {
printf("%d ", numbers[i]);
}
printf("
");
}
int main(void) {
int data[] = {3, 6, 9, 12};
int length = sizeof(data) / sizeof(data[0]);
print_numbers(data, length);
return 0;
}
Notice that the function receives both the array parameter and the length. That is the normal C pattern. If you forget to pass the size, the function cannot reliably figure it out later.
Use const when you do not modify the array
If a function only reads the array, mark the parameter const. That makes the function contract clearer and prevents accidental writes:
void print_numbers(const int numbers[], int length)
Strings are arrays too
In C, a string is a character array terminated by a null byte �.
char word[] = "hello";
That array actually stores six characters: h, e, l, l, o, and �.
This detail matters because many string bugs come from forgetting the terminator. If you manually create a character array, leave room for �.
char word[6] = {'h', 'e', 'l', 'l', 'o', '�'};
Practical rules for using arrays well
Here are the habits that make arrays easier to use safely:
- Track the array length explicitly when you pass arrays to functions.
- Use
< length, not<= length, in loops. - Reserve
sizeof(array) / sizeof(array[0])for scopes where the object is still an array. - Remember that local uninitialized arrays contain indeterminate values.
- Prefer
constfor read-only function parameters. - Leave space for the null terminator when working with strings.
A simple checklist before you index an array
| Question | Why it matters |
|---|---|
| Is the index non-negative? | Negative indexes are invalid in normal array use |
| Is the index less than the length? | Prevents out-of-bounds access |
| Is the array still in scope? | Avoids using memory that no longer belongs to it |
| Do I know the element type? | Prevents wrong arithmetic or wrong format specifiers |
Common mistakes
Off-by-one errors
The most frequent bug is an index that runs one step too far:
for (int i = 0; i <= length; i++)
The correct version is:
for (int i = 0; i < length; i++)
Using the wrong sizeof
This works:
int length = sizeof(numbers) / sizeof(numbers[0]);
This often does not work inside a function that receives an array parameter:
int length = sizeof(numbers) / sizeof(numbers[0]);
Inside that function, numbers may be a pointer, not the original array, so sizeof no longer gives the full element count. Pass the length separately.
Forgetting initialization
A local array like this:
int values[4];
does not start at zero by default. If you read from it before writing valid values, you get garbage data. If you want zeros, initialize it explicitly:
int values[4] = {0};
When arrays are the right tool
Use arrays when you need:
- A fixed-size collection of same-type values
- Fast indexed access
- Simple iteration
- Low-level control over memory layout
Arrays are a strong choice for small buffers, lookup data, fixed sets of measurements, and text handling. If you need dynamic resizing, you may eventually want dynamic allocation or a higher-level data structure, but arrays are still the starting point for a huge amount of C code.
Worked example
Here is a complete example that creates an array, updates a few values, and computes a total:
#include <stdio.h>
int main(void) {
int scores[] = {82, 91, 77, 88};
int length = sizeof(scores) / sizeof(scores[0]);
int total = 0;
for (int i = 0; i < length; i++) {
total += scores[i];
}
double average = (double)total / length;
printf("Average score: %.2f
", average);
return 0;
}
This example combines the main array tasks in one place:
- Declare the array
- Measure its length
- Loop through the values
- Aggregate data from the array
- Convert the result into a useful output
That pattern shows up constantly in C programs.
Final takeaway
Arrays in C are simple on the surface and exacting underneath. You declare them with a fixed type and size, access them with zero-based indexes, and pass them to functions along with their length. Once you internalize those rules, arrays become one of the most reliable tools in your C toolkit.
If you want to get better fast, practice with small examples: print an array, reverse an array, sum an array, and search an array for a value. Those exercises make the index rules feel automatic, which is the real milestone.