Storia della questione: Il linguaggio C è sempre stato flessibile in merito alla conversione dei tipi, per facilitare il lavoro con la memoria a basso livello e diverse piattaforme. Tuttavia, la sua sintassi concisa e la sua potenza possono facilmente portare a vulnerabilità e difetti legati a conversioni di tipo errate, specialmente quando si lavora con puntatori e aritmetica bit a bit.
Problema:
Soluzione:
Esempio di codice:
#include <stdio.h> void print_double_as_int(double d) { int i = (int)d; printf("Valore: %d\n", i); } void *ptr = malloc(16); int *ip = (int*)ptr; // Accesso alla memoria raw: consentito se ptr punta realmente a int
Caratteristiche chiave:
1. Quando è consentito castare void a un puntatore a una struttura, ed è sempre sicuro?*
Tale casting è sicuro se l'indirizzo punta realmente a un'istanza di quella struttura, altrimenti il comportamento è indefinito.
2. Cosa succede se si castano puntatori a una struttura di una lunghezza all'altra a un puntatore a una struttura con un minor o maggior numero di campi?
Accedere ai campi della "nuova" struttura porterà a letture/scritture fuori dai confini della struttura originale, possibile corruzione dei dati.
Esempio di codice:
typedef struct {int a;} S1; typedef struct {int a; int b;} S2; S1 s; S2 *ps2 = (S2*)&s; // ps2->b — accesso a "spazzatura"
3. È sicuro castare un puntatore a int a un puntatore a char per accedere ai byte di quel numero?
Questo è uno dei metodi tipici di lavoro con la memoria — l'accesso byte per byte è consentito, ma richiede cautela, poiché possono sorgere problemi di allineamento e l'ordine dei byte dipende dall'architettura (big-endian/little-endian).
Un programmatore junior per ottimizzare il tempo di accesso gestiva un pacchetto di rete, casteando un puntatore da un array raw a un puntatore a una struttura di dati con campi di tipo diverso.
Pro:
Contro:
Dopo il lavoro, ogni byte del pacchetto veniva estratto manualmente tramite memcpy.
Pro:
Contro: