Pagina 1 di 1

[C] Compatibilità tipi [risolto]

Inviato: dom 3 ago 2008, 4:31
da Dani
In un programma ho definito un tipo struct con diversi membri al suo interno, eterogenei, alcuni propri del C mentre altri definiti altrove, sempre nello stesso programma.
Secondariamente ho una funzione che riceve l'indirizzo di una variabile del tipo struct incriminato. Questa funzione ha il compito di analizzare una stringa e "compilare" i membri della struttura.
Ora il problema è avere un puntatore generico, che riesca a puntare a un membro qualsiasi della struttura e che riesca a modificarlo attraverso un assegnamento.

Ad esempio, ho la struttura:

Codice: Seleziona tutto

struct x {
   char  *a;
   xyz_t *b;
}
In una funzione devo dichiarare un puntatore ptr "compatibile" con tutti i membri e assegnargli l'indirizzo di uno di essi.

Codice: Seleziona tutto

ptr = &x->s;
A questo punto devo assegnare a ptr il valore di ritorno di una seconda funzione:

Codice: Seleziona tutto

*ptr = f()
quest'assegnamento deve andare a finire nel membro puntato da ptr, s in questo caso, esattamente come se avessi usato:

Codice: Seleziona tutto

x->s = f();
Ora come ora sto usando un int*:

Codice: Seleziona tutto

int *ptr;
ptr = (int *) &x->s;
*ptr = (int) f();
il programma funziona correttamente, ma durante le compilazione ho:

Codice: Seleziona tutto

warning: dereferencing type-punned pointer will break strict-aliasing rules
Ci sono alternative al puntatore int e posso evitare in qualche modo quel warning senza togliere dal makefile -O2 -Wall e senza aggiungere -fno-strict-aliasing ?
Diciamo che la mia è soprattuto una curiosità, come ho già detto il programma funziona, ma non sono sicuro di agire nel modo corretto. :roll:

Re: [C] Compatibilità tipi

Inviato: dom 3 ago 2008, 8:19
da ZeD
Dani ha scritto:In un programma ho definito un tipo struct con diversi membri al suo interno, eterogenei, alcuni propri del C mentre altri definiti altrove, sempre nello stesso programma.
Secondariamente ho una funzione che riceve l'indirizzo di una variabile del tipo struct incriminato. Questa funzione ha il compito di analizzare una stringa e "compilare" i membri della struttura.
Ora il problema è avere un puntatore generico, che riesca a puntare a un membro qualsiasi della struttura e che riesca a modificarlo attraverso un assegnamento.
Perdonami, ma non ho capito a che ti serve un "puntatore generico".
Cioé, se sai che &x->a è un "char*" perchè non usi una variabile di tipo "char*"?

Ad esempio, ho la struttura:

Codice: Seleziona tutto

struct x {
   char  *a;
   xyz_t *b;
}
In una funzione devo dichiarare un puntatore ptr "compatibile" con tutti i membri e assegnargli l'indirizzo di uno di essi.

Codice: Seleziona tutto

ptr = &x->s;
...s? (vabe', presumo che sia un campo tipo a o b)
A questo punto devo assegnare a ptr il valore di ritorno di una seconda funzione:

Codice: Seleziona tutto

*ptr = f()
quest'assegnamento deve andare a finire nel membro puntato da ptr, s in questo caso, esattamente come se avessi usato:

Codice: Seleziona tutto

x->s = f();
Ora come ora sto usando un int*:

Codice: Seleziona tutto

int *ptr;
ptr = (int *) &x->s;
*ptr = (int) f();
il programma funziona correttamente, ma durante le compilazione ho:

Codice: Seleziona tutto

warning: dereferencing type-punned pointer will break strict-aliasing rules
Ci sono alternative al puntatore int e posso evitare in qualche modo quel warning senza togliere dal makefile -O2 -Wall e senza aggiungere -fno-strict-aliasing ?
Beh, potresti definire ptr di tipo void*, e toglierti i casting di torno... ma non ho capito perché non puoi usare "il tipo giusto"

Diciamo che la mia è soprattuto una curiosità, come ho già detto il programma funziona, ma non sono sicuro di agire nel modo corretto. :roll:
mmm
"funziona" non credo sia sufficiente: a memoria non ci sono errori solo perché su x86 un int* e un void* hanno la stessa dimensione... ma non ci fare affidamento

Re: [C] Compatibilità tipi

Inviato: dom 3 ago 2008, 12:33
da Dani
ZeD ha scritto:Perdonami, ma non ho capito a che ti serve un "puntatore generico".
Cioé, se sai che &x->a è un "char*" perchè non usi una variabile di tipo "char*"?
Perchè la funzione non deve modificare sempre un char* ma anche variabili di tipo differente. Il suo comportamento varia in base ai parametri ricevuti, e sempre in base ad essi decido su quale variabile (e soprattutto di che tipo) agire.
Potrei effettuare gli assegnamenti direttamente sui membri della struttura, ma è una questione di leggibilità del codice (probabilmente solo per me :))
...s? (vabe', presumo che sia un campo tipo a o b)
Colpa dell'ora :D
Comunque si, intendevo a o b.
Beh, potresti definire ptr di tipo void*, e toglierti i casting di torno... ma non ho capito perché non puoi usare "il tipo giusto"
Con un puntatore a void come posso modificare l'indirizzo di una variabile non potendolo dereferenziare ?

Re: [C] Compatibilità tipi

Inviato: dom 3 ago 2008, 14:33
da absinthe
se te ne freghi dell'ansi e usi i tool gnu esiste la macro typeof !
altrimenti puoi usare un puntatore void ma poi IMHO _devi_ fare il cast se vuoi gestire il contenuto della variabile...
se non vuoi accedere direttamente alla struttura e non vuoi incasinarti la vita IMHO devi crearti dei "metodi" (ma mi pare inutile)

Codice: Seleziona tutto

typedef struct _a_useless_struct {
int a;
double b;
another_struct *my_stuff;
} my_data;

void my_data_set_int(ptr_to_my_data *ptr, int set_a_with_this_value) {
    ptr->a = set_a_with_this_value;
}

void my_data_set_double(ptr_to_my_data *ptr, double set_b_with_this_value) {
    ptr->b = set_b_with_this_value;
}

void my_data_set_another_struct_address(ptr_to_my_data *ptr, another_struct * set_my_stuff_with_this_address) {
    ptr->my_stuff = set_my_stuff_with_this_address;
}
detto ciò per chiarire il concetto, puoi usare l'overloading delle funzioni per fare quello che ti serve!

Codice: Seleziona tutto

typedef struct _a_useless_struct {
int a;
double b;
another_struct *my_stuff;
} my_data;

//zero-th overloaded version for int: first instance of my_data_set_item
void my_data_set_item(ptr_to_my_data *ptr, int set_a_with_this_value) {
    ptr->a = set_a_with_this_value;
}
//first overloaded version for double
void my_data_set_item(ptr_to_my_data *ptr, double set_b_with_this_value) {
    ptr->b = set_b_with_this_value;
}
//second overloaded version for addresses
void my_data_set_item(ptr_to_my_data *ptr, another_struct * set_my_stuff_with_this_address) {
    ptr->my_stuff = set_my_stuff_with_this_address;
}
M

Re: [C] Compatibilità tipi

Inviato: lun 4 ago 2008, 1:20
da Dani
Credo di aver risolto, usando un puntatore a puntatore a void.

Codice: Seleziona tutto

void **ptr;
ptr = (void **) &mystruct->type_ptr;
*ptr = (type_cast *) value;
Così facendo non ottengo warning, ma mi restano due dubbi:
- Questa soluzione presenta problemi su architetture non x86 ?
- Se il void** ptr punta ad un int, *ptr = (int *) atoi ("10") è corretto ?

[edit]
No non è vero, anche così facendo gcc mi dà il warning se dal makefile non tolgo -O2 o -fno-strict-aliasing (con -O2 abilitato). :(

Re: [C] Compatibilità tipi

Inviato: ven 8 ago 2008, 4:04
da Dani
Anche se qui menzionano il termine di "puntatore generico", a quanto pare, questo in C non esiste.
Un void* non fa al caso mio, in quanto non dereferenziabile, mentre un void** sembra essere non portabile.
Anche l'overloading delle funzioni in C non è una cosa fattibile.
Ho risolto semplicemente modificando il codice, alla fine mi stavo solo complicando la vita inutilmente !

Re: [C] Compatibilità tipi

Inviato: ven 8 ago 2008, 18:06
da absinthe
Dani ha scritto: Anche l'overloading delle funzioni in C non è una cosa fattibile.
why :?:

M

Re: [C] Compatibilità tipi

Inviato: ven 8 ago 2008, 18:25
da Dani
absinthe ha scritto:
Dani ha scritto: Anche l'overloading delle funzioni in C non è una cosa fattibile.
why :?:

M
Non è previsto in c !
Compilando questo:

Codice: Seleziona tutto

void f (int x) {
 return;
 }
void f (double y) {
 return;
 }
 int main (void) {
  return 0;
 }
ottengo:

Codice: Seleziona tutto

error: conflicting types for 'f'
error: previous definition of 'f' was here

Re: [C] Compatibilità tipi [risolto]

Inviato: sab 9 ago 2008, 12:46
da absinthe
opporc... #-o vedi che succede a fare tutto con il sottogruppo c del c++ :oops:

M