Rozumiem, że [[T; 4]; 3]
i [T; 12]
mają taki sam układ w pamięci. Jaki jest najlepszy sposób na konwersję wartości między tymi typami? Czy mogę zamienić odniesienie na jedno na odniesienie do drugiego? Czy mogę uniknąć kopiowania wszystkich elementów? Czy potrzebuję unsafe
?Jaki jest najlepszy sposób na konwersję [[T; 4]; 3] w [T; 12]?
Odpowiedz
Tak, możesz zamienić odniesienie na [[T; 4]; 3]
na odniesienie do [T; 12]
, ale tylko z niebezpiecznym kodem, używając mem::transmute
. Najlepiej jest zawrzeć to w funkcji, aby wynikowy odnośnik miał przypisany odpowiedni czas życia, ponieważ w przeciwnym razie transmute
umożliwiłoby uzyskanie odniesienia o dłuższym czasie życia niż powinno mieć odniesienie.
fn convert<'a>(a: &'a [[u8; 4]; 3]) -> &'a [u8; 12] {
unsafe { std::mem::transmute(a) }
}
ten może zostać skrócony dzięki zasadom życia elizja:
fn convert(a: &[[u8; 4]; 3]) -> &[u8; 12] {
unsafe { std::mem::transmute(a) }
}
Choć gdy ma do czynienia z niebezpiecznym kodem, chciałbym zrozumieć, jeśli preferowane bardziej wyraźny wersję!
Nota prawna: Nie jestem naprawdę świetny w sprawie niskiego poziomu rdzy Rusta, ale nie wiem, co jest uważane za "dobrą praktykę" w rdzy niskiego poziomu. Porady tutaj podane mogą nie być dobrymi pomysłami. Wrzucam je tutaj, ponieważ ... no cóż, działają.
You could transmute them. Problem polega na tym, że będzie to kopia, dokumentacja mówi, że jest to odpowiednik połączenia memcpy
. To nie jest to, czego chciał, ale tutaj jest to w każdym razie:
fn main() {
let a: [[u8; 4]; 3] = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]];
let b: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
println!("a: {:?}", a);
println!("b: {:?}", b);
let c = unsafe { std::mem::transmute::<[[u8; 4]; 3], [u8; 12]>(a) };
println!("c: {:?}", c);
}
Twój innych opcji is to work with a raw pointer:
fn main() {
let a: [[u8; 4]; 3] = [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]];
let b: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
println!("a: {:?}", a);
println!("b: {:?}", b);
let c = &a as *const _ as *const [u8; 12];
// Or it can be this: let c = &mut a as *mut [[u8; 4]; 3];
for i in 0..12 {
let p = c as *const u8;
let v = unsafe { *p.offset(i) };
println!("{}", v);
}
}
który nie jest szczególnie wielki albo.
Wskaźnik może być również wskaźnikiem lub zmienny wskaźnik do tego samego typu (od &mut T
mogą być oddane do *mut T
), a powyższy kod działa dokładnie tak samo (z a
oznaczone zmienny):
let c = &mut a as *mut [[u8; 4]; 3];
Zastanawiam się, czy jest to jednak problem XY. Być może sposób, w jaki pracujesz z danymi, może zostać zmieniony, aby tego nie wymagać?
- 1. Jaki jest najlepszy sposób na blokowanie blokowania Spróbuj [T] w Przyszłości [T] w Scali?
- 2. Jaki jest najlepszy sposób przekonwertowania Action <T> na Func <T,Tres>?
- 3. Najszybszy sposób konwertowania T [,] na T [] []?
- 4. Jaki jest najlepszy sposób na konwersję kolekcji nietypowej na kolekcję ogólną?
- 5. Jaki jest najlepszy sposób na konwersję matrycę SymPy do tablicy numpy/matrycy
- 6. Jaki jest najlepszy sposób uzyskania ostatnich 24 godzin w wyniku T-SQL?
- 7. Jaki jest najlepszy sposób na konwersję z RectF na Rect w systemie Android?
- 8. Jaki jest najbardziej odpowiedni sposób na konwersję nibbles na u64?
- 9. Jaki jest najlepszy sposób pracy z uprawnieniami w Angular 4?
- 10. Jaki jest najlepszy sposób na skopiowanie listy?
- 11. Jaki jest najlepszy sposób na konwersję z sieci bitcount na netmask?
- 12. T-SQL UNION Na 3 stołach?
- 13. Konwertuj Seq [Opcja [T]] na Seq [T]
- 14. Jaki jest najlepszy sposób dodania jednego elementu do IEnumerable <T>?
- 15. Najlepszy sposób na konwersję czasu militarnego na czas standardowy w javascript
- 16. Jaki jest najlepszy sposób symulacji java.lang.Thread?
- 17. Podłoża T-SQL - ostatnie 3 znaki
- 18. ustalić, czy T Oczywisty [T] jest zbiorem
- 19. Jaki jest najskuteczniejszy sposób konwersji Matrycy {T} o rozmiarze 1 * N lub N * 1 w Julii na wektor {T}?
- 20. Jaki jest najlepszy sposób na seed srand()?
- 21. Jaki jest najlepszy sposób na wdrożenie "timera"?
- 22. Jaki jest najlepszy sposób na naukę CUDA?
- 23. W jaki sposób generować klasę za pomocą T i listy <T>
- 24. Jaki jest najlepszy sposób na naukę Erlanga?
- 25. Najlepszy sposób na konwersję std :: wstring do QString
- 26. Jak przekonwertować `& T` na po prostu` T`?
- 27. Jaki jest najlepszy sposób na obsługę wiadomości FBO w OpenGL?
- 28. Jaki jest pożytek z <T><T> w public static T addAndReturn (elementu T Collection <T> kolekcja) {
- 29. Android Najlepszy sposób na konwersję tablicy bajtów na bitmapę?
- 30. W jaki sposób Stream.reduce (BinaryOperator <T> akumulator)
Po prostu wyjaśnić: Czy kopia bitowa jest bitowa, jeśli odwołuje się do siebie, a nie do zawartości tablicy? Nie byłem pewien. –
@Simon: Jeśli transmutujesz _reference_ do tablicy, kopiowana jest tylko referencja. Jeśli transmutujesz _array_ bezpośrednio (tak jak w twojej odpowiedzi), wtedy cała tablica jest kopiowana. Jednak kompilator może przesłać kopię w zależności od tego, co zrobisz z wartością i sposobem kompilacji kodu (debugowanie lub wydanie). –
Świetne bez problemu. W każdym razie zostawię swoją odpowiedź jako punkt odniesienia dla siebie w przyszłości. Dzięki za wytłumaczenie :) –