Arrays in C Programming (1D, 2D & Memory Layout)

Arrays in C — conceptual cover illustration
Arrays in C — conceptual cover illustration

An array in C is a contiguous sequence of elements belonging to the exact same data type. Because all elements sit side-by-side in physical memory, the CPU can access any element in O(1) constant time through direct address arithmetic. Understanding memory layout and pointer decay is vital to working with C arrays safely.

1. Contiguous Memory Layout and 1D Array Declaration

When you declare int arr[5], the compiler reserves a contiguous block of 20 bytes (5 elements * 4 bytes each) on the stack. C uses zero-based indexing, where the first element is at arr[0] and the final element is at arr[4].

2. The O(1) Base Address Formula

How does C locate arr[i] instantly? The compiler computes the physical address using the base address formula: Address(arr[i]) = Base_Address + (i * sizeof(DataType)) Because this involves a single multiplication and addition, element lookup takes deterministic constant time regardless of array size.

int numbers[4] = {10, 20, 30, 40};
// &numbers[2] == (char*)numbers + (2 * sizeof(int))
printf("Index 2 value: %d\n", *(numbers + 2)); // Prints 30

3. 2D Arrays and Row-Major Memory Ordering

While 2D arrays are conceptually grids with rows and columns, physical computer RAM is strictly one-dimensional. C stores multi-dimensional arrays in Row-Major Order: all elements of Row 0 are placed first, followed immediately by Row 1, Row 2, and so forth.

4. Array Decay into Pointers and Bounds Protection

In most C expressions, the name of an array decays into a constant pointer to its first element (arr == &arr[0]). Crucially, C never checks array bounds at runtime. Accessing arr[10] on a 5-element array results in buffer overflow and undefined behavior.

Runnable C example

#include <stdio.h>

int main(void) {
    int scores[5] = {70, 85, 90, 65, 100};
    int grid[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };
    int n = sizeof(scores) / sizeof(scores[0]);
    int sum = 0;

    for (int i = 0; i < n; i++) {
        sum += scores[i];
    }
    printf("Elements: %d\n", n);
    printf("Sum: %d\n", sum);
    printf("Average: %.1f\n", (double)sum / n);

    printf("2D array:\n");
    for (int r = 0; r < 2; r++) {
        for (int c = 0; c < 3; c++) {
            printf("%d ", grid[r][c]);
        }
        printf("\n");
    }
    return 0;
}

Open example in compiler

Expected Output

Elements: 5
Sum: 410
Average: 82.0
2D array:
1 2 3 
4 5 6 

Frequently Asked Questions

What is the relationship between arrays and pointers in C?

An array name evaluates to the address of its first element. Writing arr[i] is syntactically identical to *(arr + i). However, unlike pointers, array base addresses cannot be reassigned.

Why does passing an array to a function lose its size information?

When passed to a function, arrays decay into a pointer to the first element. The sizeof() operator inside the function returns the pointer size (8 bytes on 64-bit systems) rather than the array capacity. You must always pass the array length as a separate argument.

Related learn