PDA

View Full Version : [C] Puntatori void e confronti


Gica78R
22-04-2005, 13:20
Ciao a tutti!

Ho gia' chiesto su un altro forum circa questo problema, ma non ne sono venuto a capo.

Sono in ambiente Linux e sto usando la funzionevoid* shmat(int shmid, const void *shmaddr, int shmflag);che aggancia un segmento di memoria condivisa allo spazio di indirizzi del processo chiamante, ma il discorso si puo' fare con qualsiasi funzione che ritorna un void*.

In un programma e' possibile fare questa cosa qui:if (shmat(<parametri>)<0)
{
...
}
else { ... } e va tutto bene, nonostante si stia comparando un void* (il valore ritornato dalla funzione) con un int (lo zero). Inoltre il compilatore non da nessun avviso circa questo confronto. Il significato di quel codice e' di testare il valore di ritorno di shmat per vedere se c'e' stato un errore; infatti, la funzione ritorna -1 in caso di fallimento, o, in caso di successo, il puntatore al segmento di memoria agganciato.
Se pero' sono io a definire una mia funzione del tipovoid* Funzione()
{ return -1; }con il testif (Funzione()<0)
{ ... }
else { ... }non si entra mai nel primo ramo dell' if ma sempre nell' else (perche' il valore riportato da Funzione() e' 0xFFFFFFFF, che e' maggiore di 0). Inoltre il compilatore mi avvisa che sto comparando un puntatore con un intero senza fare un cast.
Qualcuno sa spiegarmi come mai questa diversita' di comportamento tra la shmat e Funzione(), nonostante entrambe ritornino un void*?

Grazie,
Gica :cool:

ilsensine
22-04-2005, 13:43
Ciao a tutti!
(il valore ritornato dalla funzione) con un int (lo zero). Inoltre il compilatore non da nessun avviso circa questo confronto.
Non avvisa in quanto "0" indica anche "NULL", e un confronto tra puntatori è valido. Mettici ad es. "1" e vedrai che il warning viene generato.
Non è una buona idea però confrontare così. Io metterei if ((long)shmat(<parametri>)==-1).
Questa differenza dovrebbe spiegarti anche il punto successivo (l'if senza cast non ti funziona in quanto void * è più logicamente un "unsigned long" che un "long").

Gica78R
23-04-2005, 10:35
Non avvisa in quanto "0" indica anche "NULL", e un confronto tra puntatori è valido. Mettici ad es. "1" e vedrai che il warning viene generato.
Non è una buona idea però confrontare così. Io metterei if ((long)shmat(<parametri>)==-1).
Questa differenza dovrebbe spiegarti anche il punto successivo (l'if senza cast non ti funziona in quanto void * è più logicamente un "unsigned long" che un "long").
Boh, non riesco ancora a capire! O meglio, quello che mi hai appena spiegato l'ho capito, ma non chiarisce ancora il mio dubbio: shmat() puo' ritornare -1, e in tal caso l'espressione shmat()<0 e' vera. Se invece e' Funzione() a ritornare -1, non solo l'espressione Funzione()<0 risulta sempre falsa, ma viene anche generato il warning sul confronto tra tipi di dato differenti...
Ho dato un'occhiata ai sorgenti di shmat per vedere come e' fatta l'istruzione return, ma non ci ho capito una mazza!
void *
shmat (shmid, shmaddr, shmflg)
int shmid;
const void *shmaddr;
int shmflg;
{
void *__unbounded result;
void *__unbounded raddr;

#if __BOUNDED_POINTERS__
size_t length = ~0;
struct shmid_ds shmds;
/* It's unfortunate that we need to make another system call to get
the shared memory segment length... */
if (shmctl (shmid, IPC_STAT, &shmds) == 0)
length = shmds.shm_segsz;
#endif

result = (void *__unbounded) INLINE_SYSCALL (ipc, 5, IPCOP_shmat,
shmid, shmflg,
(long int) __ptrvalue (&raddr),
__ptrvalue ((void *) shmaddr));
if ((unsigned long) result <= -(unsigned long) SHMLBA)
result = raddr;

return BOUNDED_N (result, length);
}

sempre se si tratta della shmat giusta, perche' ce ne sono un paio...

Ciao

Gica78R
26-04-2005, 08:45
Nessun' altra idea? :mc:

:cry: Gica

ilsensine
26-04-2005, 13:32
Boh, non riesco ancora a capire! O meglio, quello che mi hai appena spiegato l'ho capito, ma non chiarisce ancora il mio dubbio: shmat() puo' ritornare -1, e in tal caso l'espressione shmat()<0 e' vera
E' la documentazione che è poco chiara: shmat non ritorna un numero; in caso di errore ritorna un puntatore di valore ~0UL che, se interpretato come long, vale -1.
Nota che il confronto "<0" è sbagliato in ogni caso: puntatori validi sono ad es. 0x80ae7f00, che se interpretati come numeri con segno sono <0!