DMarlon Studio

Lesson 1 · 1 of 20

Pointers to pointers and arithmetic · C

Walk C arrays with pointer arithmetic, subtract pointers, and use a pointer to a pointer so a function can change where another pointer points.

C · Pointers to pointers and arithmetic in DMarlon Studio: the example's code and its output in the terminal

Pointer arithmetic counts in elements, not bytes: if p points at prices[0], then p + 2 points at prices[2] and *(p + 2) is the same as prices[2]. The compiler multiplies by the size of the type, which is why (char *)(p + 1) - (char *)p gives 8, the bytes in a double.

Subtracting two pointers into the same array gives the number of elements between them, as a ptrdiff_t (printed with %td). (prices + n) - p is 5, and cheapest - prices turns a pointer into its index. Pointing one past the last element, like prices + n, is allowed for comparisons but not for reading with *.

A function gets copies of its arguments. For find_cheapest to change the cheapest pointer in main, it receives its address, &cheapest, and the parameter is a pointer to a pointer, double **. Inside, *cheapest is main's pointer and **cheapest is the price it points at.

The most common use of ** is a list of strings: shops is an array of const char * ending in NULL, just like argv. const char **s walks the list: *s is each string and **s its first letter.

In DMarlon Studio, you write this program in the Console target and build and run it with one click (F9).

Code · main.c

#include <stdio.h>#include <string.h>// Receives the address of a pointer and makes it point at the cheapest price.void find_cheapest(double *prices, int n, double **cheapest) {    *cheapest = prices;    for (double *p = prices + 1; p < prices + n; p++)        if (*p < **cheapest) *cheapest = p;}int main(void) {    double prices[] = {4.50, 3.20, 5.10, 2.95, 3.80};    int n = sizeof prices / sizeof prices[0];    // Pointer arithmetic: p + 2 moves two elements, not two bytes.    double *p = prices;    printf("First: %.2f, third: %.2f\n", *p, *(p + 2));    printf("Bytes from p to p + 1: %td\n", (char *)(p + 1) - (char *)p);    printf("Elements from start to end: %td\n", (prices + n) - p);    double *cheapest = NULL;    find_cheapest(prices, n, &cheapest);    printf("Cheapest: %.2f at index %td\n", *cheapest, cheapest - prices);    // A list of strings is an array of pointers: char ** walks through it.    const char *shops[] = {"Bakery", "Market", "Kiosk", NULL};    for (const char **s = shops; *s != NULL; s++)        printf("Shop %td: %-7s first letter %c, %zu letters\n",               s - shops, *s, **s, strlen(*s));    const char **second = shops + 1;    printf("Through **: %s starts with %c\n", *second, **second);    return 0;}

Output · cc main.c -o main && ./main

First: 4.50, third: 5.10
Bytes from p to p + 1: 8
Elements from start to end: 5
Cheapest: 2.95 at index 3
Shop 0: Bakery  first letter B, 6 letters
Shop 1: Market  first letter M, 6 letters
Shop 2: Kiosk   first letter K, 5 letters
Through **: Market starts with M

Key points

  • p + i moves i elements; *(p + i) is p[i].
  • Subtracting pointers gives elements, printed with %td.
  • To change a pointer from a function, pass &pointer and take a T **.
  • Walk an array of strings with char ** until NULL.

Exercise

Write find_dearest with the same shape as find_cheapest and use both to print the highest price, the lowest price and how many elements apart they are.