2016-01-09 7 views
6

Patrząc na unix-socket natknąłem ten kod:Dlaczego konieczne jest wykonanie dwóch rzutów na zmienny surowy wskaźnik po kolei?

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 
}; 

byłem ciekaw tych liniach w szczególności:

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

Dlaczego jest to konieczne, aby wykonać dwa rzuty na zmienny surowego wskaźnik w wiersz? Dlaczego nie wystarczyło by rzucać tylko raz?

Odpowiedz

7

timeout na przykład odpowiada parametr *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 

timeout w tym pliku jest zdefiniowany jako:

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

Więc to od rodzaju libc::timeval. Teraz rozważmy:

&mut timeout as *mut _ as *mut _ 

najpierw trzeba &mut timeout tak, że jest typu &mut libc::timeval. Następnie należy wykonać as *mut _, aby przymusić go do surowego zmiennego wskaźnika typu wywnioskowanego, który w tym przypadku jest tego samego typu: libc::timeval, więc pełny typ do tej pory to: *mut libc::timeval, który nie jest zgodny z typem parametru *mut c_void. Ostateczny as *mut _ ponownie podaje typ celu, który jest teraz parametrem typu *mut c_void, więc ostatecznie wymusza to *mut libc::timeval na *mut c_void.

+0

Ah, rozumiem. Dzięki za wytłumaczenie! Pytanie uzupełniające: czy rdza sugeruje drugą konwersję ze względu na sygnaturę 'getsockopt' lub jest po prostu tym, że * co * wskaźnik jest rzutowany na' * mut c_void', jeśli często przeprowadzam konwersję? Nawet dla dowolnego oryginalnego typu, powiedzmy 'i mut Vec '? –

+0

Nie, na szczęście nie! To byłoby przerażające: S To właśnie z powodu sygnatury 'getsockopt', szczególnie dlatego, że pozycja wyrażenia ma ten typ celu. To samo by miało miejsce np. jeśli robiłeś 'let ptr: * mut c_void = & mut timeout jako * mut _ jako * mut _;'. –

Powiązane problemy