traduccion ps4 lenguaje language juego rust

ps4 - rust traduccion



¿Cómo se debe hacer aritmética de punteros en Rust? (1)

Sé que la respuesta es "no deberías" ... pero por el bien de la discusión, ¿cómo deberías hacerlo?

Por ejemplo, si desea escribir una alternativa a Vec<T> que funcionó de manera diferente.

Veo que puede hacer ''algo que compila y ejecuta'' al transmutar * mut T valores de * mut T en u64 y agregarlos, luego transmutarlos de nuevo en * mut T y leer el valor en el puntero (vea el ejemplo a continuación). Parece funcionar, pero deja algunas preguntas abiertas:

  1. ¿Un puntero a * mut T siempre encajará en u64 ?

  2. ¿La write() en un puntero no seguro desencadena problemas de alias de puntero cuando los datos son un bloque de datos arbitrario (es decir, no de tipo administrado) de libc:calloc ?

  3. Esto solo funciona porque estoy usando un tipo primitivo ( f64 ). Si se tratara de un objeto de datos reales, primero tendría que forget() el objeto; pero, ¿puede simplemente write() un * mut T en un objetivo y luego read() nuevo felizmente más tarde si el tipo es complejo y tiene registros secundarios?

  4. ¿Es esta realmente la manera correcta de hacer esto? Parece extremadamente incómodo. Esperaba encontrar algún ptrtoint() inseguro ptrtoint() / inttoptr() , pero no puedo encontrar nada de eso.

Ejemplo

extern crate libc; use std::mem::size_of; use std::ptr::write; use std::ptr::read; use std::mem::transmute; use libc::calloc; use libc::free; use libc::c_void; struct Array { length: usize, data: *mut f64, } impl Array { fn new(length: usize) -> Array { unsafe { Array { length: length, data: calloc(size_of::<f64>(), length) as *mut f64, } } } fn set(&mut self, offset: usize, value: f64) { if offset < self.length { unsafe { let root: *mut f64 = transmute(transmute::<*mut f64, u64>(self.data) + (size_of::<f64>() * offset) as u64); println!("Write: [{:?}] -> {}", root, value); write(root, value); } } else { println!("Write: Nope: [{}] is out of bounds", offset); } } fn get(&self, offset: usize) -> f64 { if offset < self.length { unsafe { let root: *const f64 = transmute(transmute::<*mut f64, u64>(self.data) + (size_of::<f64>() * offset) as u64); let rtn = read::<f64>(root); println!("Read: [{:?}] -> {}", root, rtn); return rtn; } } println!("Read: Nope: [{}] is out of bounds", offset); 0.0 } } impl Drop for Array { fn drop(&mut self) { unsafe { free(self.data as *mut c_void); } } } fn main() { let mut tmp = Array::new(4); tmp.set(0, 100.5); tmp.set(1, 101.5); tmp.set(2, 102.5); tmp.set(3, 103.5); tmp.set(4, 104.5); tmp.get(0); tmp.get(1); tmp.get(2); tmp.get(3); tmp.get(4); }

Salida

Write: [0x7f04bdc1e080] -> 100.5 Write: [0x7f04bdc1e088] -> 101.5 Write: [0x7f04bdc1e090] -> 102.5 Write: [0x7f04bdc1e098] -> 103.5 Write: Nope: [4] is out of bounds Read: [0x7f04bdc1e080] -> 100.5 Read: [0x7f04bdc1e088] -> 101.5 Read: [0x7f04bdc1e090] -> 102.5 Read: [0x7f04bdc1e098] -> 103.5 Read: Nope: [4] is out of bounds