DMarlon Studio

Lección 5 · 5 de 20

const y punteros · C

Distinga en C entre puntero a const, puntero const y los dos a la vez, y use const en los parámetros para prometer que una función solo lee.

C · const y punteros en DMarlon Studio: el código del ejemplo y su salida en la terminal

`const` hace que el compilador impida escribir en algo. Con punteros hay dos cosas que se pueden proteger: los datos a los que apunta y el propio puntero. La regla para leerlo: const afecta a lo que tiene a su izquierda o, si no hay nada, a lo de su derecha.

const char *shop es un puntero a const: no se puede escribir *shop = 'x', pero shop sí puede apuntar a otra cadena. Es el tipo correcto para las cadenas literales y para casi cualquier parámetro de texto, como el de count_upper, que mueve s por la cadena sin cambiarla.

char *const first = city es un puntero const: siempre apunta a city, pero a través de él sí se escribe, y first[0] = 'M' pone la mayúscula a Madrid. const double *const rate protege las dos cosas.

En los parámetros, const es una promesa a quien llama. show(const Book *b) solo lee el libro: si dentro se intentara b->stock = 0, el programa no compilaría. sell(Book *b, …) no lleva const porque cambia el stock, y eso se ve ya en su declaración.

Las líneas comentadas del ejemplo son errores de compilación a propósito: quite el // de una de ellas para ver el mensaje del compilador.

Código · 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;}

Salida · 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%

Para recordar

  • const T *p: no se escribe en *p; p puede moverse.
  • T *const p: p no se mueve; *p se puede escribir.
  • const T *const p: ninguna de las dos cosas.
  • Ponga const en los parámetros que la función solo lee.

Ejercicio

Escriba double stock_value(const Book *books, int n) que sume precio por stock de un array de libros, y compruebe que el compilador protesta si dentro intenta cambiar un precio.