DMarlon Studio

Lesson 5 · 5 of 20

const and pointers · C

Tell apart a pointer to const, a const pointer and both at once in C, and use const parameters to promise that a function only reads.

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

`const` makes the compiler refuse writes to something. With pointers there are two things you can protect: the data it points at and the pointer itself. The reading rule: const applies to what is on its left or, if there is nothing there, to what is on its right.

const char *shop is a pointer to const: you cannot write *shop = 'x', but shop can point to another string. It is the right type for string literals and for almost every text parameter, like the one in count_upper, which moves s along the string without changing it.

char *const first = city is a const pointer: it always points at city, but you can write through it, and first[0] = 'M' capitalises Madrid. const double *const rate protects both things.

On parameters, const is a promise to the caller. show(const Book *b) only reads the book: trying b->stock = 0 inside would not compile. sell(Book *b, …) has no const because it changes the stock, and you can tell from its declaration alone.

The commented-out lines in the example are deliberate compile errors: remove the // from one of them to see the compiler's message.

Code · main.c

#include <ctype.h>#include <stdio.h>typedef struct { const char *title; double price; int stock; } Book;// const Book *: the function promises to only read the book.void show(const Book *b) {    printf("%-15s %6.2f  stock %2d\n", b->title, b->price, b->stock);    // b->stock = 0;  // error: assignment to a read-only location}void sell(Book *b, int units) { b->stock -= units; }  // Book *: may change itint count_upper(const char *s) {    int n = 0;    for (; *s; s++)  // s itself moves; what it points to is read-only        if (isupper((unsigned char)*s)) n++;    return n;}int main(void) {    Book book = {"The C Language", 39.90, 12};    show(&book);    sell(&book, 3);    show(&book);    char city[] = "madrid";    const char *shop = "Libros DMarlon";  // pointer to const: can move, can't write    char *const first = city;             // const pointer: can write, can't move    first[0] = 'M';                       // first = shop; would not compile    const double vat = 0.04;    const double *const rate = &vat;      // neither the pointer nor the value    printf("%s (%d capitals) in %s, VAT %.0f%%\n", shop, count_upper(shop), city, *rate * 100);    return 0;}

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

The C Language   39.90  stock 12
The C Language   39.90  stock  9
Libros DMarlon (3 capitals) in Madrid, VAT 4%

Key points

  • const T *p: no writes to *p; p can move.
  • T *const p: p cannot move; *p can be written.
  • const T *const p: neither.
  • Mark the parameters a function only reads as const.

Exercise

Write double stock_value(const Book *books, int n) that adds up price times stock over an array of books, and check that the compiler complains if you try to change a price inside it.