Pointer arithmetic

You can add an integer to a pointer, and the result is scaled by the size of what it points at. If p is an int * holding address A, then p + 1 is A + 4 (with 4-byte ints), not A + 1. It moves one element, not one byte. A char * moves by 1, a double * by 8.

That makes walking an array natural:

int nums[3] = {5, 6, 7};
int *p = nums;      // same as &nums[0]
printf("%d\n", *(p + 2));   // 7

Notice int *p = nums; with no &. In most expressions, an array name decays into a pointer to its first element. And here is the secret: nums[i] is defined as *(nums + i). Square brackets are pointer arithmetic with nicer syntax.

Decay is also why a function cannot learn an array's length:

void show(int arr[], int n);   // arr is really an int *

Inside show, sizeof(arr) is the size of a pointer (4 here), not the array. That is why C functions that take arrays almost always take a length too.

Subtracting two pointers into the same array gives the number of elements between them. You can also do p++ to step through, and loop until p reaches an end pointer like nums + 3.

The rules: arithmetic is only defined within one array, plus the position just past its end (which you may point to but not dereference). Going further, or ordering pointers into different arrays with <, is undefined behaviour.

Try it yourself

Edit it. Break it. Run it again.
#include <stdio.h>

int total(int *arr, int n) {
    int sum = 0;
    for (int *p = arr; p < arr + n; p++) {
        sum += *p;
    }
    return sum;
}

int main(void) {
    int nums[4] = {5, 6, 7, 8};
    int *p = nums;

    printf("nums[2] = %d, *(p + 2) = %d\n", nums[2], *(p + 2));
    printf("p + 1 is %d bytes past p\n", (int)((char *)(p + 1) - (char *)p));
    printf("elements from p to p + 3: %d\n", (int)((p + 3) - p));
    printf("total = %d\n", total(nums, 4));
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

Your turn

Type it yourself. That is the whole trick.

1Walk with a pointer

Finish int count_spaces(char *s) using a pointer that moves forward with s++ until it reaches the '\0', counting the spaces. Print:

  • 3
  • 0
#include <stdio.h>

int count_spaces(char *s) {
    int count = 0;
    return count;
}

int main(void) {
    printf("%d\n", count_spaces("you type the code"));
    printf("%d\n", count_spaces("nospaces"));
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

2Brackets are optional

Print every element of vals from last to first, one per line, without using square brackets on vals anywhere. Use *(vals + i) or a moving pointer. Expected:

  • 40
  • 30
  • 20
  • 10
#include <stdio.h>

int main(void) {
    int vals[4] = {10, 20, 30, 40};

    for (int i = 0; i < 4; i++) {
        printf("%d\n", *(vals + i));
    }
    return 0;
}
Ctrl/Cmd + Enter runs. Esc, then Tab, leaves the editor.

Code editor. Press Control or Command plus Enter to run the code. Tab indents; to move focus out of the editor, press Escape and then Tab.