Skip to content
Laviyx Learn

Try

C course menu

Pointers and Arrays in C: Array Decay, a[i] vs *(a + i), and Arrays of Strings

Understand how arrays and pointers relate in C: array-to-pointer decay, why a[i] equals *(a + i), the differences between arrays and pointers (sizeof and assignment), pointers to strings, arrays of strings, and pointers to whole arrays.

Intermediate6 min readUpdated
On this page

Arrays and pointers are closely related in C, but they are not the same thing. Understanding the relationship explains how array parameters, strings and indexing really work.

Array decay#

In most expressions, an array's name is automatically converted ("decays") to a pointer to its first element:

C
int a[] = {5, 10, 15};
int *p = a;                  /* same as p = &a[0] */
printf("%d\n", p == &a[0]);
printf("%d %d\n", *p, p[2]);
Output
1
5 15

That is why passing an array to a function passes a pointer (Parameters).

a[i] is *(a + i)#

Indexing is defined in terms of pointer arithmetic: a[i] means exactly *(a + i). It works the same on arrays and pointers:

C
int a[] = {5, 10, 15, 20};
int *p = a + 1;              /* points to 10 */
printf("%d %d\n", a[2], *(a + 2));
printf("%d %d\n", p[0], p[2]);   /* indexes are relative to p */
Output
15 15
10 20

Where arrays and pointers differ#

Array int a[4]Pointer int *p
What it isStorage for 4 intsStorage for one address
sizeofWhole array (16 bytes)The pointer (8 bytes on 64-bit)
Can be assignedNo: a = ... is an errorYes: p = other
& givesPointer to the whole arrayAddress of the pointer variable
C
int a[4] = {0};
int *p = a;
printf("%zu %zu\n", sizeof a, sizeof p);
Output
16 8

(64-bit system.) Decay does not happen for sizeof, &, or a string literal used to initialise a char array.

Strings: array vs pointer#

C
char arr[] = "pune";          /* a modifiable array of 5 chars */
const char *ptr = "pune";     /* points to a read-only literal */

arr[0] = 'P';                 /* fine */
ptr = "delhi";                /* fine: the pointer now points elsewhere */
printf("%s %s\n", arr, ptr);
Output
Pune delhi

Arrays of strings#

An array of const char * is the usual way to store a list of fixed strings. Each element points to a literal of any length:

C
#include <stdio.h>

int main(void) {
    const char *days[] = {"Mon", "Tue", "Wednesday", "Thu", "Fri"};
    int n = sizeof days / sizeof days[0];
    for (int i = 0; i < n; i++) {
        printf("%-10s first letter %c\n", days[i], days[i][0]);
    }
    return 0;
}
Output
Mon        first letter M
Tue        first letter T
Wednesday  first letter W
Thu        first letter T
Fri        first letter F

A 2D char array, char days[5][10], instead stores the characters themselves in fixed-size rows. Use it when you need to modify the strings.

Pointer to a whole array#

int (*row)[3] is a pointer to an array of 3 ints. It is what a 2D array decays to, so stepping it moves a whole row:

C
int grid[2][3] = {{1, 2, 3}, {4, 5, 6}};
int (*row)[3] = grid;        /* points to grid[0] */
row++;                       /* now points to grid[1] */
printf("%d %d\n", (*row)[0], row[0][2]);
Output
4 6

The parentheses matter: int *row[3] would be an array of 3 pointers.

Practice#

Practice exercise

Write const char *longest(const char *words[], int n) that returns the longest word in an array of strings, and use it on {"array", "pointer", "decay", "dereference", "null"}.

Show solution
C
#include <stdio.h>
#include <string.h>

const char *longest(const char *words[], int n) {
    const char *best = words[0];
    for (int i = 1; i < n; i++) {
        if (strlen(words[i]) > strlen(best)) best = words[i];
    }
    return best;
}

int main(void) {
    const char *words[] = {"array", "pointer", "decay", "dereference", "null"};
    printf("%s\n", longest(words, 5));
    return 0;
}
Output
dereference

Key takeaway#

Finished this lesson?