Pointers and Arrays

Arrays and pointers are closely linked in C. In most expressions an array's name turns into a pointer to its first element, and a[i] is defined in terms of pointer arithmetic. That's why arrays are passed to functions so cheaply — and why the function loses track of their length.

Array decay

When you use an array's name in an expression, it decays into a pointer to element 0:

C
#include <stdio.h>

int main(void) {
    int primes[] = { 2, 3, 5, 7, 11 };
    int *p = primes;            // same as &primes[0]

    printf("%d %d\n", *p, primes[0]);
    printf("same address? %s\n", p == &primes[0] ? "yes" : "no");
    printf("p[3] = %d\n", p[3]);   // a pointer can be indexed like an array
    return 0;
}
Output
2 2
same address? yes
p[3] = 7

a[i] means *(a + i)

Indexing is defined as pointer arithmetic: a[i] is exactly *(a + i), "the element i places after the start". Adding to a pointer moves it by whole elements, not bytes (next lesson):

C
#include <stdio.h>

int main(void) {
    double temps[] = { 18.5, 21.0, 19.25 };
    for (int i = 0; i < 3; i++) {
        printf("%.2f %.2f\n", temps[i], *(temps + i));
    }
    return 0;
}
Output
18.50 18.50
21.00 21.00
19.25 19.25

Arrays as function parameters

Because of decay, a function never receives an array — only a pointer. These three declarations are identical:

C
double average(double values[10], size_t n);
double average(double values[], size_t n);
double average(double *values, size_t n);

The size in the first form is ignored. Inside the function, sizeof values is the size of a pointer, not the array, and compilers warn if you try:

C
#include <stdio.h>

double average(double values[], size_t n) {
    printf("sizeof values = %zu\n", sizeof values);
    double sum = 0;
    for (size_t i = 0; i < n; i++) sum += values[i];
    return sum / n;
}

int main(void) {
    double data[] = { 1, 2, 3, 4, 5, 6 };
    printf("%.1f\n", average(data, 6));
    return 0;
}
Compiler warnings
main.c:4:44: warning: sizeof on array function parameter will return size of 'double *' instead of 'double[]' [-Wsizeof-array-argument]

That's why C functions always take the length as a separate argument (or use a terminator, as strings do).

Where arrays and pointers differ

Array int a[5]Pointer int *p
StorageHolds 5 intsHolds one address
sizeof20 (whole array)8 (a pointer, on 64-bit systems)
Can be reassigned?No — a = … is an errorYes — p = other
&&a is a pointer to the whole array&p is the pointer's own address
C
#include <stdio.h>

int main(void) {
    int a[5] = { 0 };
    int *p = a;
    printf("sizeof a = %zu, sizeof p = %zu\n", sizeof a, sizeof p);
    return 0;
}
Output
sizeof a = 20, sizeof p = 8

Strings: array or pointer?

The difference matters most with strings:

C
#include <stdio.h>

int main(void) {
    char word[] = "cat";          // an array: a modifiable copy of the text
    const char *label = "dog";    // a pointer to a read-only string literal

    word[0] = 'b';                // fine
    label = "cow";                // fine: the pointer now points elsewhere
    printf("%s %s\n", word, label);
    printf("%zu %zu\n", sizeof word, sizeof label);
    return 0;
}
Output
bat cow
4 8

Passing part of an array

Because a function just gets a pointer, you can pass any slice by pointing into the middle:

C
#include <stdio.h>

int sum(const int *values, size_t n) {
    int total = 0;
    for (size_t i = 0; i < n; i++) total += values[i];
    return total;
}

int main(void) {
    int months[12] = { 5, 8, 6, 9, 12, 15, 18, 17, 13, 10, 7, 6 };
    printf("whole year: %d\n", sum(months, 12));
    printf("summer (Jun-Aug): %d\n", sum(months + 5, 3));
    printf("last quarter: %d\n", sum(&months[9], 3));
    return 0;
}
Output
whole year: 126
summer (Jun-Aug): 50
last quarter: 23

Try it yourself

Write find, which returns a pointer to the first element equal to a target, or NULL. Use it to change that element in place.

Try it yourself · main.c
Edit the code, copy it into main.c, then compile and run it with cc -std=c17 -Wall main.c -o main && ./main. How to set up a C compiler
Output
12 20 7 0 3