Repository 32bit  Forum
Repository 64bit  Wiki

da double ** a const double **

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.

da double ** a const double **

Messaggioda lamarozzo » mer gen 16, 2008 17:36

Stavo compilando un mio programma e mi sono imbattuto in una caratteristica del C che non conoscevo (e chissà quante altre sono :lol: ).

Ho una variabile dichiarata come double** il cui contenuto vorrei assegnare ad una variabile che punta ad una variabile costante. La mia prima idea è stata

Codice: Seleziona tutto
int main()
{
   double **slacky;
   const double **slackware;
   slackware=slacky;
   return 0;   
}


Ma googlando un po' ho scoperto che si tratta di un errore previsto dallo standard per evitare altri problemi (quali la possibilità di aggirare la constness di una variabile).

In un forum C++ ho trovato che la soluzione al mio problema è la seguente:

Codice: Seleziona tutto
int main()
{
   double **slacky;
   const double * const* slackware;
   slackware=slacky;
   return 0;   
}


Effettivamente se compilo il suddetto programma con g++ tutto fila liscio. Usando gcc invece continua a darmi

warning: assignment from incompatible pointer type

Sapevo che il C non è esattamente un sottinsieme del C++ ma non pensavo di trovare questa differenza di comportamento.

Come faccio ad implementare correttamente la stessa cosa in C?
Avatar utente
lamarozzo
Linux 2.6
Linux 2.6
 
Messaggi: 732
Iscritto il: mer lug 13, 2005 23:00
Località: Roma
Desktop: xfce
Distribuzione: archlinux

Re: da double ** a const double **

Messaggioda Blizzard » mer gen 16, 2008 18:31

ciao,

puoi postare la fonte da cui hai preso quel codice... o comunque spiegarmi come funziona???
non è che ci ho capito molto ad intuito :P
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: da double ** a const double **

Messaggioda Blizzard » mer gen 16, 2008 18:34

comunque con un cast esplicito il warning va via... non so se ci possono essere futuri problemi.

Codice: Seleziona tutto
    int main()
    {
       double **slacky;
       const double **slackware;
       slackware=(const double**)slacky;
       return 0;   
    }


EDIT: ho letto dopo scusate :P cancellate tutto quello che dico sopra
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: da double ** a const double **

Messaggioda lamarozzo » mer gen 16, 2008 19:07

Blizzard ha scritto:ciao,

puoi postare la fonte da cui hai preso quel codice... o comunque spiegarmi come funziona???


Ciao,
il codice che ho postato è solo un esempio ridotto ai minimi termini in cui si fa un cast implicito da un tipo ad un altro. Secondo gcc sono problematici sia double** -> const double** che double** -> const double* const*, mentre per g++ solo il primo rappresenta un problema (e difatti lo è perchè può generare situazioni potenzialmente pericolose: per un esempio vedi in fondo a questo link http://www.parashift.com/c++-faq-lite/c ... #faq-18.17 ).

Come dici giustamente tu con un cast esplicito il compilatore non segnala problemi: ma è giusto? Non vorrei che la cosa fosse compiler dependent e un giorno che sposto il programma su un'altra macchina mi esplode tutto.
Avatar utente
lamarozzo
Linux 2.6
Linux 2.6
 
Messaggi: 732
Iscritto il: mer lug 13, 2005 23:00
Località: Roma
Desktop: xfce
Distribuzione: archlinux

Re: da double ** a const double **

Messaggioda Blizzard » mer gen 16, 2008 19:29

ciao

Come dici giustamente tu con un cast esplicito il compilatore non segnala problemi: ma è giusto? Non vorrei che la cosa fosse compiler dependent e un giorno che sposto il programma su un'altra macchina mi esplode tutto.

di solito il cast esplicito dovrebbe funzionare ovunque perchè è una forzatura totale. Pertanto IMHO (ma può darsi che moltissimi mi smentiranno) non dovresti avere problemi di compilazione su altri sistemi e compilatori.

Il fatto è che i cast contribuiscono a generare codice poco sicuro... magari l'utilizzo di tali sistemi può portare a errori nascosti.
Nel c++ la questione dovrebbe essere leggermente diversa. Molto è affidato ai cast impliciti e sul manuale di Lippman/Lajoie è fortemente consigliato lasciar fare quanto possibile ai cast impliciti. Per tutto il resto sono stati definiti "operatori" (non so se è corretto dirlo) di cast appositi const_cast static_cast ecc... proprio per evitare la forzatura totale dei tipi.
Penso comunque che il tuo caso sia da vedere bene... dato che entrano in gioco puntatori e punatori const.

Lascio pertanto la parola agli esperti :p

P.S.
prima mi riferivo al codice c++ che non ho capito come funziona la dichiarazione strana... o meglio inconsueta :D
Avatar utente
Blizzard
Master
Master
 
Messaggi: 1509
Iscritto il: mar gen 02, 2007 22:53
Nome Cognome: Giovanni Santostefano
Slackware: 12.2
Kernel: 2.6.27.7-smp
Desktop: Fluxbox

Re: da double ** a const double **

Messaggioda puzuma » gio gen 17, 2008 13:34

se ho capito bene il problema mi sa che hai bisogno dell'operatore const_cast
The quiet ones are the ones who change the world. The loud ones only take the credit.
Avatar utente
puzuma
Linux 2.4
Linux 2.4
 
Messaggi: 481
Iscritto il: mar lug 04, 2006 16:14
Località: Udine
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0

Re: da double ** a const double **

Messaggioda puzuma » gio gen 17, 2008 13:59

puzuma ha scritto:se ho capito bene il problema mi sa che hai bisogno dell'operatore const_cast



infatti non ho capito il problema ... const_cast è un operatore di c++ non di c
The quiet ones are the ones who change the world. The loud ones only take the credit.
Avatar utente
puzuma
Linux 2.4
Linux 2.4
 
Messaggi: 481
Iscritto il: mar lug 04, 2006 16:14
Località: Udine
Nome Cognome: Stefano Salvador
Slackware: current
Kernel: 2.6.32.2
Desktop: KDE 4.4.0

Re: da double ** a const double **

Messaggioda lamarozzo » gio gen 17, 2008 17:07

Sì, mi servirebbe la soluzione per il C. Per il C++, come ho fatto vedere, il problema non si pone perchè il compilatore non lancia nessun warning. Magari la soluzione con il cast esplicito è quella giusta, ma non ne sono sicuro.
Avatar utente
lamarozzo
Linux 2.6
Linux 2.6
 
Messaggi: 732
Iscritto il: mer lug 13, 2005 23:00
Località: Roma
Desktop: xfce
Distribuzione: archlinux

Re: da double ** a const double **

Messaggioda Dani » gio gen 17, 2008 18:01

Provato a vedere se comporta problemi l'uso di qualcosa simile a:
Codice: Seleziona tutto
int main()
{
   double **slacky;
   const double * const* slackware;
   slackware = (const double* const*) slacky;
   return 0;   
}


?
Dani
Linux 3.x
Linux 3.x
 
Messaggi: 1447
Iscritto il: mer apr 26, 2006 0:52
Desktop: gnome
Distribuzione: arch

Re: da double ** a const double **

Messaggioda lamarozzo » gio gen 17, 2008 18:39

Effettivamente con il casto esplicito il compilatore non si lamenta. Vuol dire che sarà la soluzione giusta, anche se pensavo che il cast a const potesse essere fatto in maniera implicita.

Grazie.
Avatar utente
lamarozzo
Linux 2.6
Linux 2.6
 
Messaggi: 732
Iscritto il: mer lug 13, 2005 23:00
Località: Roma
Desktop: xfce
Distribuzione: archlinux

Re: da double ** a const double **

Messaggioda nuitari » gio gen 17, 2008 18:58

ma sei sicuro di quello che hai scritto?
la dichiarazione di una variabile come const implica che il valore non deve variare nel corso dell'applicativo, successivamente alla dichiarazione. per cui, se dichiari in un qualsiasi modo "slackware" come const, il successivo assegnamento (slackware=..) è in ogni caso un errore.

Non è che volevi fare una cosa del genere?

Codice: Seleziona tutto
#include <stdio.h>

int main()
{
   double ** slacky;
   double ** const slackware = slacky;

   printf("slacky:%p slackware:%p\n", (void *)slacky, (void *)slackware);

   return 0;
}


I cast sono problematici nella misura in cui vengono usati per costringere il compilatore ad accettare quelli che a tutti gli effetti sono errori.
Avatar utente
nuitari
Linux 2.6
Linux 2.6
 
Messaggi: 777
Iscritto il: dom ott 14, 2007 11:51
Località: San Colombano al Lambro
Slackware: 12.0

Re: da double ** a const double **

Messaggioda lamarozzo » gio gen 17, 2008 19:36

nuitari ha scritto:ma sei sicuro di quello che hai scritto?
la dichiarazione di una variabile come const implica che il valore non deve variare nel corso dell'applicativo, successivamente alla dichiarazione. per cui, se dichiari in un qualsiasi modo "slackware" come const, il successivo assegnamento (slackware=..) è in ogni caso un errore.


Il cast è voluto. Ho una variabile double** che punta ad una matrice bidimensionale e voglio passarla ad una funzione. Voglio permettere alla funzione di leggere la matrice ma non voglio assolutamente che possa modificarla. Quindi nella dichiarazione della funzione ci sarà qualcosa del tipo

Codice: Seleziona tutto
void dummy(const double* const* matrice);


mentre il main ha qualcosa del tipo

Codice: Seleziona tutto
double **matrice;
...
dummy(matrice);


Soltanto che così il compilatore segnala un warning dicendo che c'è un problema con la conversione. La cosa migliore che si può fare per bypassare il warning sembrerebbe essere l'utilizzo di un cast esplicito, e cioè:

Codice: Seleziona tutto
double **matrice;
...
dummy((const double* const*)matrice);


anche se è un po' bruttino.

Ovviamente mi piacerebbe sapere se ci sono altre soluzioni o se sto sbagliando.
Avatar utente
lamarozzo
Linux 2.6
Linux 2.6
 
Messaggi: 732
Iscritto il: mer lug 13, 2005 23:00
Località: Roma
Desktop: xfce
Distribuzione: archlinux

Re: da double ** a const double **

Messaggioda nuitari » ven gen 18, 2008 22:26

puoi postare il codice nella sua interezza per favore? almeno la parte interessata, con la dichiarazione della matrice.

EDIT:

Credo di aver colto.
Il motivo per cui non è giusto effettuare un cast da (type **) a (const type **) è perchè si tratta di un operazione pericolosa.
Guarda questo codice d'esempio:

Codice: Seleziona tutto
class Foo {
 public:
   void modify();  // make some modify to the this object
 };
 
 int main()
 {
   const Foo x;
   Foo* p;
   const Foo** q = &p;  // q now points to p; this is (fortunately!) an error
   *q = &x;             // p now points to x
   p->modify();         // Ouch: modifies a const Foo!!
   ...
 }


Mi sembra chiaro no? La sintassi giusta ovviamente è (const type * const *).

Il C++ accetta questa forma, i compilatori C pur accettandola (in quanto comune) segnalata uno warning perchè secondo la specifica ANSI C89:

both operands are pointers to qualified or unqualified types versions
of compatible types, and the type pointed to by the left has all the
qualifiers as the type pointed to by the right
[...]
For two qualified types to be compatible, both shall have the identical
qualified versions of a compatible type


Per cui picche.
Mentre è possibile assegnare un "top-level qualifier" extra ai pointer che l'argomento puntato non ha, questo non è permesso per gli elementi interni.
Per cui ad esempio (const type *) = (type *) sarebbe permesso (ma non nella C90).
Avatar utente
nuitari
Linux 2.6
Linux 2.6
 
Messaggi: 777
Iscritto il: dom ott 14, 2007 11:51
Località: San Colombano al Lambro
Slackware: 12.0

Re: da double ** a const double **

Messaggioda lamarozzo » lun gen 21, 2008 9:27

Grazie nuitari.
Mi era chiaro che il cast double** -> const double ** è vietato perchè pericoloso ma non avevo chiaro in cosa differisse lo standard C++ con quello del C per quanto riguarda invece il cast corretto, double** -> const double* const*. Ora cercherò di approfondire un po' le cose che hai scritto, se ho problemi ti faccio un fischio :-'
Avatar utente
lamarozzo
Linux 2.6
Linux 2.6
 
Messaggi: 732
Iscritto il: mer lug 13, 2005 23:00
Località: Roma
Desktop: xfce
Distribuzione: archlinux

Re: da double ** a const double **

Messaggioda nuitari » lun gen 21, 2008 13:43

Sai cosa, il fatto è che const in C è un *paliativo*. Il C non offre un vero controllo sui dati, dato che lavora più che altro con la memoria. Basti vedere la discussione che c'è stata sugli array in un altro post..

Il const serve per fare *quel controllo in più*, ma non va ne abusato ne bisogna pensare di essere *salvi* una volta che lo si è usato. Lo ha detto pure Torvalds tra l'altro =) In C vale sempre la regola *devi sapere quel che stai facendo*.

In C++ invece il discorso è diverso. Gli oggetti const differiscono da i non cost in quanto a struttura, cambiano proprio i membri, per cui non è sempre corretto fare un cast da const a non const per via delle differenze intrinseche, non si tratta solo di una questione di *compilazione*.
Avatar utente
nuitari
Linux 2.6
Linux 2.6
 
Messaggi: 777
Iscritto il: dom ott 14, 2007 11:51
Località: San Colombano al Lambro
Slackware: 12.0

Prossimo

Torna a Programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 0 ospiti