Strutture (struct) in C
In questa pagina 6
Definizione
Una struct raggruppa in un unico tipo più campi di tipo anche diverso (come una tupla con nomi o un semplice oggetto Python con soli attributi).
struct punto {
double x;
double y;
};
struct punto p = {1.0, 2.0};
struct punto q = {.y = 5.0, .x = 3.0}; /* inizializzatori con nome */
p.x = 4.0; /* accesso ai campi con . */Con typedef si dà un nome più corto al tipo:
typedef struct {
char nome[32];
int matricola;
double media;
} Studente;
Studente s = {"Ada", 123456, 28.5};- Una
structsi può assegnare (q = p;copia tutti i campi, anche gli array interni) ma non confrontare con==. sizeof(Studente)può essere maggiore della somma dei campi per l'allineamento in memoria (padding).
Struct e funzioni
Una struct passata per valore viene copiata per intero; per modificarla o per evitare la copia di strutture grandi si passa un puntatore. Con un puntatore i campi si raggiungono con ->: ps->media equivale a (*ps).media.
double distanza(struct punto a, struct punto b) { /* per valore */
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
void aggiorna_media(Studente *ps, double nuovo_voto, int n_esami) {
ps->media = (ps->media * (n_esami - 1) + nuovo_voto) / n_esami;
}
struct punto medio(struct punto a, struct punto b) { /* struct come valore di ritorno */
struct punto m = {(a.x + b.x) / 2, (a.y + b.y) / 2};
return m;
}Restituire una struct è il modo pulito di restituire più valori insieme (alternativa ai parametri puntatore di Puntatori in CUn puntatore contiene un indirizzo di memoria; operatori & e *, NULL, puntatori come parametri per modificare variabili del chiamante, aritmetica dei puntatori, legame tra array e puntatori, const, puntatori a puntatori.Puntatori in C →).
Array di struct
Studente classe[3] = {
{"Ada", 1, 29.0},
{"Alan", 2, 27.5},
{"Grace", 3, 30.0},
};
int migliore = 0;
for (int i = 1; i < 3; i++)
if (classe[i].media > classe[migliore].media)
migliore = i;
printf("%s\n", classe[migliore].nome);Struct dinamiche
Studente *ps = malloc(sizeof *ps);
if (ps != NULL) {
strcpy(ps->nome, "Ada");
ps->matricola = 1;
free(ps);
}Struct autoreferenziali
Una struct non può contenere se stessa, ma può contenere un puntatore al proprio tipo. È la base delle strutture collegate:
typedef struct nodo {
int valore;
struct nodo *succ; /* serve il nome "struct nodo": il typedef non è ancora completo */
} Nodo;Uso in Liste concatenateLista concatenata semplice: nodi allocati dinamicamente collegati da puntatori; inserimento e rimozione in testa, scorrimento, ricerca, inserimento ordinato, deallocazione; confronto dei costi con l'array; versione in Python.Liste concatenate → e, come tipo che nasconde la rappresentazione, in Tipi di dato astrattiUn ADT è definito dalle operazioni e dal loro comportamento, non dalla rappresentazione; interfaccia e implementazione; realizzazione in Python con le classi e in C con header e tipo opaco; esempio di un ADT Frazione.Tipi di dato astratti →.
Errori tipici
ps.campocon un puntatore (serveps->campo) os->campocon una struct (serves.campo).- Aspettarsi che una funzione modifichi una struct ricevuta per valore.
- Dimenticare il
;dopo la}della definizione. - Copiare una struct che contiene puntatori pensando di copiare anche i dati puntati: si copiano solo gli indirizzi (copia superficiale, come in Liste in Pythonlist come sequenza mutabile (array dinamico); indici, slicing e assegnamento a fette; metodi e loro costo; aliasing, copia superficiale e profonda; list comprehension; liste annidate e matrici.Liste in Python →).