Strutture e Puntatori in linguaggio C

Una struttura dati, quando passata come argomento di una funzione, viene sempre passata per copia. In altre, parole, viene creata una copia della struttura originale, che viene passata alla funzione.

In questa lezione vedremo come passare strutture per riferimento, cioè come passare un puntatore alla struttura stessa. Vedremo anche come dichiarare e manipolare puntatori a strutture in linguaggio C.

Puntatori e struct

Un puntatore può puntare ad un qualunque tipo di dato, double, int, char, e può anche puntare ad una struttura dati struct.

In questo caso, la sintassi per dichiarare un puntatore ad una struttura dipende se usiamo una struct etichettata oppure un tipo definito con typedef.

Prendiamo una struct di esempio:

struct Punto {
    int x;
    int y;
};

typedef struct Punto TipoPunto;

Dichiarare un puntatore ad una struct etichettata Punto è semplice:

struct Punto *puntoPtr;

Dichiarare un puntatore ad una struct definita con typedef è altrettanto semplice:

TipoPunto *puntoPtr;
Definizione

Puntatori a Strutture

Un puntatore in linguaggio C può puntare anche ad una struttura dati struct.

Per definire un puntatore ad una struttura struct etichettata, si usa la seguente sintassi:

struct NomeStruttura *puntatore;

Per definire un puntatore ad una struttura definita con typedef, si usa la seguente sintassi:

TipoStruttura *puntatore;

Per i puntatori a strutture, tutte le operazioni tipiche dei puntatori sono ammesse:

  • Assegnamento di un indirizzo di memoria ad un puntatore;
  • Aritmetica dei puntatori;
  • Assegnamento di un puntatore ad un altro.

Ciò che merita una discussione a parte riguarda l'accesso ai membri di una struttura tramite un puntatore.

Operatore Freccia

Prendiamo il seguente esempio:

struct Punto {
    int x;
    int y;
};

struct Punto punto = { 10, 20 };

struct Punto *punto_ptr = &punto;

il puntatore punto_ptr punta alla struttura punto. Si tratta di un puntatore a tutti gli effetti, per cui possiamo applicare ad esso l'operatore di dereferenziazione * per accedere al contenuto puntato:

*(punto_ptr);

Questo ci restituirà la struttura punto stessa. Per accedere ai membri della struttura, possiamo usare l'operatore .:

(*punto_ptr).x = 30;
(*punto_ptr).y = 40;

Questa sintassi, però, è piuttosto verbosa.

Per fortuna, in C esiste un'operatore apposito per accedere ai membri di una struttura tramite un puntatore: l'operatore freccia ->.

punto_ptr->x = 30;
punto_ptr->y = 40;

Questo codice è equivalente a quello sopra, ma molto più leggibile.

Infatti vale sempre l'uguaglianza:

punto_ptr->x == (*punto_ptr).x
Definizione

Operatore Freccia ->

In linguaggio C, l'operatore freccia -> è usato per accedere ai membri di una struttura tramite un puntatore.

La sintassi è la seguente:

struct nome_struttura {
    /* Campi */
};

struct nome_struttura struttura;

struct nome_struttura *ptr;

ptr = &struttura;

ptr->campo = valore;

L'operatore freccia equivale semanticamente a:

(*ptr).campo = valore;

Passaggio di Strutture a Funzioni per Riferimento

Ora che sappiamo come dichiarare e manipolare puntatori a strutture, possiamo studiare come passare strutture a funzioni per riferimento.

Il meccanismo è identico in tutto e per tutto a quello usato per passare qualsiasi altro tipo di dato per riferimento: passiamo il puntatore alla struttura. Dobbiamo solo ricordarci di usare l'operatore freccia per accedere ai membri della struttura.

Consideriamo un esempio. Supponiamo di avere una funzione che incrementa le coordinate di un punto:

struct Punto {
    double x;
    double y;
};

void incrementaPunto(struct Punto *punto, double dx, double dy) {
    punto->x += dx;
    punto->y += dy;
}

Possiamo chiamare questa funzione passando un puntatore alla struttura Punto:

struct Punto punto = { 10.0, 20.0 };

incrementaPunto(&punto, 5.0, 5.0);

Dopo la chiamata a incrementaPunto, la struttura punto avrà le coordinate (15.0, 25.0).

In questo modo, possiamo passare strutture a funzioni per riferimento, evitando di copiare la struttura stessa.

Definizione

Passaggio di Strutture a Funzioni per Riferimento

Per passare una struttura a una funzione per riferimento, si passa un puntatore alla struttura stessa e si accede ai membri della struttura tramite l'operatore freccia ->.

void funzione(struct Struttura *puntatore) {
    puntatore->campo = valore;
}

In Sintesi

In questa lezione abbiamo visto come dichiarare e manipolare puntatori a strutture in linguaggio C. Abbiamo imparato a usare l'operatore freccia -> per accedere ai membri di una struttura tramite un puntatore.

Abbiamo anche studiato come passare strutture a funzioni per riferimento, passando un puntatore alla struttura stessa.