CodeMIRAI
0 XP

Pointers and arrays

2 min read 4 runnable examples Quiz included

The pointers lesson showed that an array's name works as a pointer to its first element. This lesson follows that idea further.

Pointer arithmetic

C
#include <stdio.h>

int main() {
    int a[5] = {10, 20, 30, 40, 50};
    int *p = a;                  // the same as &a[0]

    printf("%d\n", *p);          // 10
    printf("%d\n", *(p + 2));    // 30
    p++;                         // move to the next element
    printf("%d\n", *p);          // 20
    p = p + 2;                   // move two more
    printf("%d\n", *p);          // 40
    return 0;
}

Adding 1 to a pointer moves it to the next element, not the next byte. For a pointer to int, that's 4 bytes along: the compiler scales the arithmetic by the size of the type it points to.

a[i] means *(a + i)

C
#include <stdio.h>

int main() {
    int a[4] = {3, 6, 9, 12};
    int *p = a;
    for (int i = 0; i < 4; i++) {
        printf("a[%d]=%d  *(a+%d)=%d  p[%d]=%d\n", i, a[i], i, *(a + i), i, p[i]);
    }
    printf("%d\n", &a[2] == a + 2);    // 1: the same address
    return 0;
}

Array indexing is pointer arithmetic: a[i] is defined as *(a + i), "start at a and move i elements along". That's why the first index is 0.

Walking a string with a pointer

C
#include <stdio.h>

int main() {
    char word[] = "pointer";
    char *p = word;
    while (*p != '\0') {
        printf("%c ", *p);
        p++;
    }
    printf("\n");
    return 0;
}

Instead of counting with an index, the pointer itself moves along the string until it reaches the terminating '\0'. A great deal of classic C code is written in this style.

Arrays passed to functions are pointers

C
#include <stdio.h>

void doubleAll(int *values, int n) {
    for (int i = 0; i < n; i++) {
        *(values + i) = *(values + i) * 2;    // the same as values[i] *= 2
    }
}

int sum(int values[], int n) {    // in a parameter list, int values[] means int *values
    int total = 0;
    for (int i = 0; i < n; i++) total += values[i];
    return total;
}

int main() {
    int nums[4] = {1, 2, 3, 4};
    doubleAll(nums, 4);
    printf("%d %d %d %d\n", nums[0], nums[1], nums[2], nums[3]);
    printf("sum: %d\n", sum(nums, 4));
    return 0;
}

Passing an array passes the address of its first element. That's why a function can change the caller's array, and also why it needs the length passed separately: a pointer alone doesn't know how many elements follow it.

The sizeof trap

C
void show(int values[]) {
    printf("%zu\n", sizeof(values));    // 8 on most systems: the size of a pointer
}

int main(void) {
    int nums[10];
    printf("%zu\n", sizeof(nums));      // 40: the whole array
    show(nums);
    return 0;
}

Inside the function, values is only a pointer, so sizeof reports the size of a pointer. sizeof(array) / sizeof(array[0]) counts elements only where the real array is declared.

Pointer subtraction and one past the end

C
int a[5] = {10, 20, 30, 40, 50};
int *start = &a[1];
int *end = &a[4];
printf("%d\n", (int) (end - start));    // 3: the number of elements between them

for (int *q = a; q < a + 5; q++) {      // stop one past the last element
    printf("%d ", *q);
}

Subtracting two pointers into the same array gives the number of elements between them, and < tells you which comes first. a + 5 points just past the last element: it's fine to compare against, but must never be dereferenced. (The in-browser C interpreter can't run these two yet; the server's compiler can.)

const and string literals

C
const char *msg = "Hello";    // the characters can't be changed through msg
msg = "Bye";                  // fine: msg itself can point somewhere else
msg[0] = 'J';                 // error: the text is read-only

char buffer[] = "Hello";      // an array of your own, which you can change
buffer[0] = 'J';              // fine: now "Jello"

A string literal like "Hello" lives in read-only memory. Point at it with a const char *, and copy it into an array when you need to change it.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.