Skip to content
  • Pointer Arithmetic · C

Pointer Arithmetic

LearnViaNotes @learnvianotes· 3 min read

Adding n to a pointer moves it by n elements, not bytes: p + 1 advances by sizeof *p. Arithmetic is only valid within one array (plus one-past-the-end).

C
#include <stdio.h>

int main(void) {
    int a[] = {10, 20, 30, 40};
    int *p = a;                  /* &a[0] */
    char *c = (char *)a;

    printf("%d %d %d\n", *p, *(p + 1), *(p + 3));
    printf("int step  = %td bytes\n", (char *)(p + 1) - (char *)p);
    printf("char step = %td bytes\n", (c + 1) - c);

    int *end = a + 4;            /* one past the end: may be compared, never dereferenced */
    printf("elements between = %td\n", end - p);
    for (int *q = a; q < end; q++) printf("%d ", *q);
    printf("\n");
    return 0;
}
Output
10 20 40
int step  = 4 bytes
char step = 1 bytes
elements between = 4
10 20 30 40

What is allowed

OperationAllowed?Result
p + n, p - n, p++, p--Yes, within the array / one past endPointer
p - q (same array)Yesptrdiff_t element count (%td)
p < q, p == qYes (relational only within one array)0 / 1
p + q, p * 2, p / 2No — compile error—
p + n beyond one-past-endUndefined even without dereferencing—
Arithmetic on void *Not in standard C (GNU extension treats it as char *)—

Idioms

C
#include <stdio.h>

size_t length(const char *s) {
    const char *p = s;
    while (*p) p++;                 /* walk to the terminator */
    return (size_t)(p - s);         /* pointer difference = count */
}

void copy(char *dst, const char *src) {
    while ((*dst++ = *src++) != '\0') { }   /* classic K&R strcpy */
}

int sum(const int *begin, const int *end) {
    int s = 0;
    while (begin != end) s += *begin++;     /* *(begin++) */
    return s;
}

int main(void) {
    char buf[16];
    copy(buf, "pointer");
    int v[] = {1, 2, 3, 4, 5};
    printf("%s %zu %d\n", buf, length(buf), sum(v, v + 5));
    return 0;
}
Output
pointer 7 15

Precedence of * and ++

C
#include <stdio.h>

int main(void) {
    int a[] = {10, 20, 30};
    int *p = a;
    int x;
    x = *p++;    printf("*p++   -> %d, now *p = %d\n", x, *p);   /* read, then move */
    x = *++p;    printf("*++p   -> %d\n", x);                    /* move, then read */
    p = a;
    x = ++*p;    printf("++*p   -> %d, a[0] = %d\n", x, a[0]);   /* increment the value */
    x = (*p)++;  printf("(*p)++ -> %d, a[0] = %d\n", x, a[0]);   /* read, then increment value */
    return 0;
}
Output
*p++   -> 10, now *p = 20
*++p   -> 30
++*p   -> 11, a[0] = 11
(*p)++ -> 11, a[0] = 12

Walking off the end

C — heap-buffer-overflow caught by AddressSanitizer
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int *a = malloc(3 * sizeof *a);
    if (!a) return 1;
    for (int *p = a; p <= a + 3; p++)   /* <= : writes a[3] */
        *p = 0;
    printf("%d\n", a[0]);
    free(a);
    return 0;
}

If int *p = (int *)1000, what is p + 1?

Can you subtract two pointers? Add them?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report