2016-11-08 45 views
0

正如標題所示,我該如何去做這件事?借用借用數組的一部分作爲借來的數組

fn foo(array: &[u32; 10]) -> &[u32; 5] { 
    &array[0..5] 
} 

編譯器錯誤

error[E0308]: mismatched types 
--> src/main.rs:2:5 
    | 
2 |  &array[0..5] 
    |  ^^^^^^^^^^^^ expected array of 5 elements, found slice 
    | 
    = note: expected type `&[u32; 5]` 
    = note: found type `&[u32]` 
+0

您必須提供一個切片(或一個新的數組實例)。 AFAIK借來的切片不能安全地轉換爲借來的數組。 –

+0

長度在類型之後'&[u32; 10]'雖然我認爲你必須返回一個未分片:'fn foo(array:&[u32; 10]) - >&[u32] {&array [0..5]}' – Lee

回答

1

它仍然無法安全地做到這一點。爲了理解爲什麼,理解這些類型是如何實現是很重要的。數組保證有N個初始化元素。它不能變得更小或更大。在編譯時,這些保證允許刪除數組的大小方面,而數組只佔用N * sizeof(元素)空間。

這意味着,[T; N][T; M]是不同類型的(當N!= M),你不能將一個其他的參考。

慣用解決方案是使用一個切片代替:

fn foo(array: &[u32; 10]) -> &[u32] { 
    &array[0..5] 
} 

切片包含一個指向該數據和該數據的長度,從而移動該邏輯從編譯時運行時間。


因爲有人會想這樣做不安全的方式,我將介紹的是編譯和出現產生正確的輸出代碼。我不知道是否確實安全或正確。

use std::mem; 

fn foo(array: &[u32; 10]) -> &[u32; 5] { 
    unsafe { 
     let data = array.as_ptr(); 
     mem::transmute(data.offset(3)) 
    } 
} 

fn main() { 
    let input = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 
    let output = foo(&input); 
    println!("{:?}", output); 
} 

請注意,初始偏移量發生在函數中,但長度不是 - 這是在類型系統中編碼的。你可以通過指定一個偏移量來導致崩潰,導致崩潰,導致返回值的末尾超出定義的內存末尾。

2

arrayref使用宏(和編譯時常量切片邊界,當然)實現了一個安全的接口來執行此操作。

Their readme解釋

數組引用的目標是使有效利用涉及數組引用,而不是分區來情況的API,其中的參數必須有一個給定的尺寸。

let addr: &[u8; 16] = ...; 
let mut segments = [0u16; 8]; 
// array-based API with arrayref 
for i in 0 .. 8 { 
    segments[i] = read_u16_array(array_ref![addr,2*i,2]); 
} 

這裏array_ref![addr,2*i,2]宏允許我們採取一個數組參照由兩個字節組成的切片在2開始* I。除了語法(不如切片更好),它基本上與切片方法相同。然而,這段代碼明確地表明在調用者和函數簽名中都需要精確的兩個字節。