consideri il seguente programma di esempio:Conversione di un puntatore a una struttura per il suo primo membro
#include <stdio.h>
struct base {
int a, b;
};
struct embedded {
struct base base;
int c, d;
};
struct pointed {
struct base* base;
int c, d;
};
static void base_print(struct base* x) {
printf("a: %d, b: %d\n", x->a, x->b);
}
static void tobase_embedded(void* object) {
base_print(object); // no cast needed, suitably converted into first member.
}
static void tobase_pointed(void* object) {
struct base* x = *(struct base**) object; // need this cast?
base_print(x);
}
int main(void) {
struct embedded em = {{4, 2}};
struct pointed pt = {&em.base};
tobase_embedded(&em);
tobase_pointed(&pt);
return 0;
}
compilato con:
$ gcc -std=c99 -O2 -Wall -Werror -pedantic -o main main.c
Il risultato atteso è:
$ ./main
a: 4, b: 2
a: 4, b: 2
La C99 lo standard dice questo sul primo membro di una struttura:
C99 6.7.2.1 (13): Un puntatore a un oggetto struttura, opportunamente convertito, punta al suo membro iniziale ... e viceversa. Ci può essere padding senza nome dentro come oggetto struttura, ma non all'inizio.
Nel programma di esempio, un puntatore a struct embedded
viene convertito in un puntatore a struct base
(attraverso void*
) senza la necessità di un cast esplicito.
E se invece il primo membro è un puntatore alla base come in struct pointed
? Non sono sicuro del cast entro il tobase_pointed
. Senza il cast, viene stampato il garbage, ma nessun avviso/errore di compilazione. Con il cast vengono stampati i valori corretti per base.a
e base.b
, ma ciò non significa molto se si verifica un comportamento non definito.
Il cast per convertire struct pointed
nel suo primo membro struct base*
è corretto?
Il primo membro di 'struct pointed' è un puntatore a' struct base'. Ciò richiederà il dereferenziamento dell'oggetto void *. Ma non è possibile dereferenziare 'void *' senza dire al compilatore come dereferenziare il puntatore, quindi una necessità di cast. – alvits