2016-01-09 5 views
6

Se si guarda a unix-socket, mi sono imbattuto in questo codice:Perché sarebbe necessario eseguire due cast in un puntatore raw mutevole in una riga?

let timeout = unsafe { 
    let mut timeout: libc::timeval = mem::zeroed(); 
    let mut size = mem::size_of::<libc::timeval>() as libc::socklen_t; 
    try!(cvt(libc::getsockopt(self.0, 
           libc::SOL_SOCKET, 
           kind, 
           &mut timeout as *mut _ as *mut _, 
           &mut size as *mut _ as *mut _))); 
    timeout 
}; 

ero curioso di queste linee, in particolare:

&mut timeout as *mut _ as *mut _, 
&mut size as *mut _ as *mut _ 

Perché è necessario eseguire due calchi a un puntatore RAW mutabile in una riga? Perché non sarebbe stato sufficiente lanciare solo una volta?

risposta

7

Il timeout ad esempio corrisponde a un parametro *mut c_void:

pub unsafe extern fn getsockopt(sockfd: c_int, level: c_int, optname: c_int, 
           optval: *mut c_void, optlen: *mut socklen_t) -> c_int 

Il timeout in quel file è definito come:

let mut timeout: libc::timeval = mem::zeroed(); 

Quindi è di tipo libc::timeval. Consideriamo ora:

&mut timeout as *mut _ as *mut _ 

Per prima cosa devi &mut timeout in modo che sia di tipo &mut libc::timeval. Quindi esegui as *mut _ per costringerlo a un puntatore mutevole non elaborato di un tipo dedotto, che in questo caso è lo stesso tipo di libc::timeval, quindi il tipo completo finora è: *mut libc::timeval, che non corrisponde al tipo di parametro *mut c_void. L'ultimo as *mut _ deduce di nuovo il tipo di destinazione, che ora è il tipo di parametro *mut c_void, in modo da forzare lo *mut libc::timeval allo *mut c_void.

+0

Ah, ho capito. Grazie per il chiarimento! Domanda successiva: ruggine deduce la seconda conversione a causa della firma di 'getsockopt' o è solo che * ogni * puntatore viene lanciato su * * mut c_void' se faccio la conversione abbastanza spesso? Anche per un tipo originale arbitrario, diciamo '& mut Vec '? –

+0

Nah, per fortuna no! Sarebbe spaventoso: S È davvero a causa della firma di 'getsockopt', in particolare perché la posizione dell'espressione ha quel tipo di bersaglio. Lo stesso sarebbe il caso, ad es. se stai facendo 'let ptr: * mut c_void = & mut timeout come * mut _ as * mut _;'. –