# Introduction to C Arrays

> Learn how C arrays store fixed-size sequences, how to initialize and iterate over them, and when an array expression converts to a pointer.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2020-02-05 | Updated: 2026-07-18 | Topics: [C](https://flaviocopes.com/tags/clang/) | Canonical: https://flaviocopes.com/c-arrays/

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:

```c
int prices[5];
```

Its size is fixed for its lifetime. [C](https://flaviocopes.com/c-introduction/) 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:

```c
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:

```c
int prices[5] = { 1, 2, 3, 4, 5 };
```

When an initializer is present, the compiler can infer the length:

```c
int prices[] = { 1, 2, 3, 4, 5 };
```

If you provide fewer initializers than elements, the remaining elements are initialized to zero:

```c
int prices[5] = { 1, 2 }; /* { 1, 2, 0, 0, 0 } */
```

You can also assign each element after the definition:

```c
int prices[5];

prices[0] = 1;
prices[1] = 2;
prices[2] = 3;
prices[3] = 4;
prices[4] = 5;
```

Or use a loop:

```c
#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:

```c
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](https://flaviocopes.com/c-pointers/) to its first element. This is often called array-to-pointer conversion or array decay:

```c
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:

```c
#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](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf).
