是否可以在Rust中使用运行时确定大小的堆栈分配数组?

是否可以在Rust中使用运行时确定大小的堆栈分配数组?,rust,Rust,是否有一种等价的alloca在Rust中创建可变长度数组 我正在寻找以下C99代码的等效代码: void go(int n){ 整数数组[n]; // ... } 否 在Rust中这样做需要在堆栈上存储动态大小的类型(DST),如[i32],而该语言不支持这种功能 更深层次的原因是,据我所知,LLVM并不真正支持这一点。我相信你能做到,但这会严重干扰优化。因此,我不知道任何近期计划允许这样做。这不可能直接实现,因为在支持它的语言中没有直接的语法 也就是说,C99的这一特殊功能是有争议的,它有一定

是否有一种等价的
alloca
在Rust中创建可变长度数组

我正在寻找以下C99代码的等效代码:

void go(int n){
整数数组[n];
// ...
}

在Rust中这样做需要在堆栈上存储动态大小的类型(DST),如
[i32]
,而该语言不支持这种功能

更深层次的原因是,据我所知,LLVM并不真正支持这一点。我相信你能做到,但这会严重干扰优化。因此,我不知道任何近期计划允许这样做。

这不可能直接实现,因为在支持它的语言中没有直接的语法

也就是说,C99的这一特殊功能是有争议的,它有一定的优势(缓存局部性&绕过malloc),但也有缺点(容易炸毁堆栈,阻碍许多优化,可能会将静态偏移变为动态偏移,…)

现在,我建议您改用
Vec
。如果您有性能问题,那么您可以研究所谓的“小向量优化”。我经常在需要性能的C代码中看到以下模式:

SomeType数组[64]={};
SomeType*指针,*动态_指针;

if(n)您始终可以从c导入alloca函数。如果您添加某种溢出检查,您甚至可以使其安全。@ker:这不太可能。
alloca
不是真正的函数,它更像是编译器的固有功能。至少对于LLVM,它是实际的IR指令,因此没有直接的“导入”方法它。你需要能够编写内联IR,而你现在不能。这让我想知道那些家伙导入了什么:…我非常确定它现在是c标准函数()LLVM首先也是最重要的,是一个C/C++优化程序,所以它可能支持得比较好。每次我看到它被提出来时,都有人说在一个块内动态调整堆栈的大小会严重损害LLVM进行优化的能力。我从来没有找到任何可靠的证据来支持或反驳这一点,所以我或多或少地支持wh我几乎没听说过。虽然我很想在这一点上犯错:堆栈DST会相当漂亮。:)Rust现在支持DST,作为Rust 1.0 alpha的一部分@MichaelTang:Rust支持DST已经有一段时间了。除非我遗漏了什么,否则它不支持将DST存储在变量中,或者从函数返回它们。@DK:你说得很对。我很惭愧地承认,在实现DST支持之前,我昨天花了太多时间试图让它工作询问者想要什么。@malbarbo:的确,它也涉及到了不巧妙地使用类型级整数的问题!我没有想过向用户请求一个数组类型,让她指定大小。板条箱提供了这一点。@wizzwizz4。
数组
特性只针对大小的子集实现,使用起来有点麻烦。总比什么都没有好,但显然这是一个解决缺少常量泛型的办法。
Inline
变量的切片实现不应该使用该变量的大小作为边界吗?这里的示例代码是整个len 64数组的一部分。所以切片的长度是错误的。@可疑的吉姆:是的,修正了。另外,如果您想在不实际构建64个Ts的情况下尝试它,您将需要使用
[maybeuniit;64]
,但我暂时不考虑这一点。最后,正在进行的工作是能够将内联存储传递给rustc的std结构,但目前这还处于原型阶段。
enum InlineVector<T, const N: usize> {
    Inline(usize, [T; N]),
    Dynamic(Vec<T>),
}
enum SmallVector<T, const N: usize> {
    Inline(usize, [T; N]),
    Dynamic(Vec<T>),
}

impl<T: Copy + Clone, const N: usize> SmallVector<T, N> {
    fn new(v: T, n: usize) -> Self {
        if n <= N {
            Self::Inline(n, [v; N])
        } else {
            Self::Dynamic(vec![v; n])
        }
    }
}

impl<T, const N: usize> SmallVector<T, N> {
    fn as_slice(&self) -> &[T] {
        match self {
            Self::Inline(n, array) => &array[0..*n],
            Self::Dynamic(vec) => vec,
        }
    }

    fn as_mut_slice(&mut self) -> &mut [T] {
        match self {
            Self::Inline(n, array) => &mut array[0..*n],
            Self::Dynamic(vec) => vec,
        }
    }
}

use std::ops::{Deref, DerefMut};

impl<T, const N: usize> Deref for SmallVector<T, N> {
    type Target = [T];

    fn deref(&self) -> &Self::Target {
        self.as_slice()
    }
}

impl<T, const N: usize> DerefMut for SmallVector<T, N> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        self.as_mut_slice()
    }
}
fn main() {
    let mut v = SmallVector::new(1u32, 4);
    v[2] = 3;
    println!("{}: {}", v.len(), v[2])
}