Repository 32bit  Forum
Repository 64bit  Wiki

[C] Compatibilità tipi [risolto]

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.

[C] Compatibilità tipi [risolto]

Messaggioda Dani » dom ago 03, 2008 3:31

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:
Ultima modifica di Dani il ven ago 08, 2008 3:04, modificato 1 volta in totale.
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Compatibilità tipi

Messaggioda ZeD » dom ago 03, 2008 7:19

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
Avatar utente
ZeD
Linux 2.0
Linux 2.0
 
Messaggi: 112
Iscritto il: ven ott 28, 2005 11:30
Località: Terra
Slackware: 12.1

Re: [C] Compatibilità tipi

Messaggioda Dani » dom ago 03, 2008 11:33

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 ?
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Compatibilità tipi

Messaggioda absinthe » dom ago 03, 2008 13:33

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
Avatar utente
absinthe
Iper Master
Iper Master
 
Messaggi: 2354
Iscritto il: sab mag 14, 2005 23:00
Località: Prato
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze

Re: [C] Compatibilità tipi

Messaggioda Dani » lun ago 04, 2008 0:20

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). :(
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Compatibilità tipi

Messaggioda Dani » ven ago 08, 2008 3:04

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 !
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Compatibilità tipi

Messaggioda absinthe » ven ago 08, 2008 17:06

Dani ha scritto:Anche l'overloading delle funzioni in C non è una cosa fattibile.

why :?:

M
Avatar utente
absinthe
Iper Master
Iper Master
 
Messaggi: 2354
Iscritto il: sab mag 14, 2005 23:00
Località: Prato
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze

Re: [C] Compatibilità tipi

Messaggioda Dani » ven ago 08, 2008 17:25

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
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: [C] Compatibilità tipi [risolto]

Messaggioda absinthe » sab ago 09, 2008 11:46

opporc... #-o vedi che succede a fare tutto con il sottogruppo c del c++ :oops:

M
Avatar utente
absinthe
Iper Master
Iper Master
 
Messaggi: 2354
Iscritto il: sab mag 14, 2005 23:00
Località: Prato
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze


Torna a Programmazione

Chi c’è in linea

Visitano il forum: Bing [Bot] e 1 ospite