Skip to content

Intermediate · Pointers · topic 23 of 60 · 30 min

Pointers and arrays

Explanation

In most expressions an array name "decays" to a pointer to its first element, so a and &a[0] are the same address, and a[i] means exactly *(a + i). That is why arrays passed to functions arrive as pointers. But an array is not a pointer: sizeof differs, and you cannot assign to an array. Strings are walked with char pointers.

Array decay

output
int a[4] = {10, 20, 30, 40};
int *p = a;                    /* same as int *p = &a[0]; */

address   name    value
0x100     a[0]    10    ◄── p
0x104     a[1]    20
0x108     a[2]    30
0x10C     a[3]    40

p[2]       → 30      (pointers can use [] too)
*(p + 2)   → 30      (the same thing, written with arithmetic)
a[2]       → 30
*(a + 2)   → 30
a[i] is defined as *(a + i). (Funny but true: i[a] also works, because *(i + a) is the same.)

Arrays are not pointers

int a[4]int *p = a
sizeof16 (the whole array)8 (just the pointer)
Can be assigned (a = …)?NoYes (p = &other)
&a givespointer to the whole array (int (*)[4])address of the pointer variable (int **)
StorageThe 4 ints themselvesOne address

The decay happens almost everywhere: when you pass the array to a function, use it in arithmetic, or assign it to a pointer. The exceptions are sizeof a, &a, and a string literal used to initialise an array.

Walking an array with a pointer

c
int sum(const int *start, const int *end) {     /* end = one past the last element */
    int total = 0;
    for (const int *p = start; p < end; p++) total += *p;
    return total;
}
int marks[] = {78, 85, 91};
printf("%d\n", sum(marks, marks + 3));          /* 254 */

char pointers and strings

c
size_t count_char(const char *s, char c) {
    size_t n = 0;
    for (; *s != '\0'; s++) {     /* move the pointer along the string */
        if (*s == c) n++;
    }
    return n;
}
count_char("banana", 'a');        /* 3 */

const char *days[] = {"Mon", "Tue", "Wed"};    /* an array of 3 pointers to string literals */
printf("%s %c\n", days[1], days[1][0]);        /* Tue T */
Careful: A function parameter written int a[] is really int *a, so sizeof a inside the function is the size of a pointer (8), not the array. This bug silently processes only 2 ints (8 / 4) in code like for (i = 0; i < sizeof a / sizeof a[0]; i++). gcc warns "sizeof on array function parameter will return size of int *". Always pass the length.
Think of it like this: An array is a row of houses on a street; the array name used in an expression is the address of the first house. a[3] means "start at the first house and walk 3 houses along". A pointer is a slip with a house number that you can also move along the street (p++).
Tip: Prefer index notation a[i] for clarity in normal code. Pointer walking (p++) is common in string and low-level code, and you must be fluent reading both.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Pointers and arrays · 1/6

Pointers and arrays

In this lesson you will see how arrays and pointers are related.

Prefer a video by a teacher? Find free videos on “c pointers and arrays relationship array decay pointer arithmetic” on YouTube ↗

In real life: Parsing a comma-separated sensor line

A data logger on a farm receives lines like "23,61,880" (temperature, humidity, soil moisture). The parser walks the string with a char pointer, converting digits into numbers until it meets a comma or the end, which needs no extra memory.

c
int parse_fields(const char *s, int out[], int max) {
    int count = 0, value = 0, in_number = 0;
    for (const char *p = s; ; p++) {
        if (*p >= '0' && *p <= '9') { value = value * 10 + (*p - '0'); in_number = 1; }
        else {                                   /* comma or '\0' ends a field */
            if (in_number && count < max) out[count++] = value;
            value = 0; in_number = 0;
            if (*p == '\0') break;
        }
    }
    return count;
}
/* parse_fields("23,61,880", out, 3) → 3, out = {23, 61, 880} */

Practice (0/3 done)

Task 1 · Question

What does this print? int a[] = {5, 10, 15, 20}; int *p = a + 1; printf("%d %d\n", *p, p[2]);

Task 2 · Question

Inside void f(int a[]), sizeof a is the size of…

Task 3 · Code · Javascript

Simulate walking a C string with a pointer: memory is an array of character codes and p is the starting address (index). Write countChar(memory, p, code) that moves p forward until it reaches a 0 byte and counts how many bytes equal code.

Quick quiz

Question 1

1.a[i] is exactly equivalent to…

Question 2

2.Which is NOT allowed?

Question 3

3.const char *names[] = {"Asha", "Ravi"}; What is names[1][0]?

Question 4

4.Where does an array NOT decay to a pointer?

Read more (free)

Before this, learn

This topic builds on these. If something here feels new, open them first.

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

a[i] is exactly equivalent to…

Answer: *(a + i)

That is the definition of subscripting.

Which is NOT allowed?

Answer: a = p;

An array name cannot be assigned.

const char *names[] = {"Asha", "Ravi"}; What is names[1][0]?

Answer: 'R'

The first character of the second string.

Where does an array NOT decay to a pointer?

Answer: In sizeof a

sizeof (and &a) see the whole array.

char a[] = "x", b[] = "x"; What does a == b compare?Related

Answer: The addresses of the two arrays

Use strcmp for text.

From Strings are char arrays

Which copies array a (3 ints) into array b?Related

Answer: memcpy(b, a, sizeof a);

Arrays cannot be assigned; copy the bytes or loop.

From Arrays

On a typical 64-bit system, sizeof(char *) is…Related

Answer: 8

All data pointers are 8 bytes on 64-bit systems.

From Addresses and pointers

What is a dangling pointer?Related

Answer: A pointer to memory that was freed or went out of scope

Using it is undefined behaviour.

From NULL, dangling pointers and pointers to pointers

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 2 more topics in “Pointers” before its exam: Pointer arithmetic, NULL, dangling pointers and pointers to pointers.
  2. Module 5 exam: Pointers · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Dynamic memory. 60 topics left in the course before the final exam.

← Previous: Pointers and functions