2016-11-08 8 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

長さはタイプすなわち'' fn foo(array:&[u32; 10)) - >&[u32] {&array [0..5]} 'のように、スライスを返さなければならないと思っていますが、 '&[u32; 10' – Lee

答えて

1

それは安全にこれを実行することは可能ではありません。理由を理解するには、これらのタイプの実装方法を理解することが重要です。配列はN個の初期化された要素を持つことが保証されています。より小さくても大きくすることはできません。コンパイル時には、これらの保証によって配列のサイズ面が削除され、配列はN * sizeof(要素)の空間しか占めません。 [T; N][T; M]はさまざまな種類があることを意味

(ときN!= M)、あなたが他の1つの参照を変換することはできません。

慣用溶液の代わりスライスを使用することである。

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]マクロiは*私たちは2から始まる2バイトからなるスライスに配列リファレンスを取ることを可能にします。シンタックス(スライシングよりも劣る)とは別に、スライスアプローチと本質的に同じです。ただし、このコードでは、呼び出し側と関数シグネチャの両方で正確に2バイトの必要性が明示されています。

関連する問題