Introduction to C Arrays
By Flavio Copes
Learn how C arrays store fixed-size sequences, how to initialize and iterate over them, and when an array expression converts to a pointer.
An array is an object that stores a sequence of values.
Every element in a C array has the same type. You can have an array of int values, an array of double values, and so on.
The elements are stored contiguously in memory, one after another.
You can define an array that has room for 5 int values:
int prices[5];
Its size is fixed for its lifetime. C does not provide a built-in array type that grows automatically. A program that needs one can allocate and resize memory, or use another data structure.
You can use an integer constant expression for the size:
enum { SIZE = 5 };
int prices[SIZE];
At block scope, const int size = 5 is not an integer constant expression in C. Using it as an array bound creates a variable length array when the implementation supports those.
You can initialize an array when you define it:
int prices[5] = { 1, 2, 3, 4, 5 };
When an initializer is present, the compiler can infer the length:
int prices[] = { 1, 2, 3, 4, 5 };
If you provide fewer initializers than elements, the remaining elements are initialized to zero:
int prices[5] = { 1, 2 }; /* { 1, 2, 0, 0, 0 } */
You can also assign each element after the definition:
int prices[5];
prices[0] = 1;
prices[1] = 2;
prices[2] = 3;
prices[3] = 4;
prices[4] = 5;
Or use a loop:
#include <stddef.h>
int prices[5];
for (size_t i = 0; i < sizeof prices / sizeof prices[0]; i++) {
prices[i] = (int)i + 1;
}
This example uses sizeof prices / sizeof prices[0] to calculate the number of elements. It works here because prices is an actual array in this scope.
You access an element by putting its index between square brackets:
prices[0]; /* array item value: 1 */
prices[1]; /* array item value: 2 */
Array indexes start from 0, so an array with 5 items, like the prices array above, will have items ranging from prices[0] to prices[4].
Accessing an element outside that range causes undefined behavior. C does not perform automatic bounds checks.
Arrays and pointers
An array is not a pointer. They are different types of objects.
However, in most expressions, an array expression is automatically converted to a pointer to its first element. This is often called array-to-pointer conversion or array decay:
int prices[] = { 5, 4, 3 };
int *first = prices;
printf("%d\n", *first); /* 5 */
printf("%d\n", *(first + 1)); /* 4 */
The conversion does not happen in some contexts, including when the array is the operand of sizeof or unary &. That is why sizeof prices above gives the size of the entire array.
When you pass an array to a function, the parameter is adjusted to a pointer. The function does not receive the array’s length automatically:
#include <stddef.h>
#include <stdio.h>
void print_prices(const int prices[], size_t length) {
for (size_t i = 0; i < length; i++) {
printf("%d\n", prices[i]);
}
}
Pointer arithmetic is valid only within the same array object, or one position past its last element. You must never dereference the one-past pointer.
The precise array conversion rules are described in section 6.3.2.1 of the C standard. You can read the long-standing rule in WG14’s freely available C11 committee draft.
Related posts about clang: