如何用一个非零值初始化数组

How to initialize array with one non-zero value

我正在创建一个数字类型,它使用数组来存储数字。为了实现特征 One,我发现自己编写了这样的代码:

    fn one() -> Self {
        let mut ret_array = [0; N];
        ret_array[0] = 1;
        Self(ret_array)
    }

有没有其他方法可以用一个个非零元素初始化数组?

我不这么认为,不。

但是 Rust 编译器理解您想要实现的目标并且 optimizes it accordingly:

pub fn one<const N: usize>() -> [i32; N] {
    let mut ret_array = [0; N];
    ret_array[0] = 1;
    ret_array
}


pub fn one_with_length_5() -> [i32; 5] {
    one()
}
example::one_with_length_5:
        mov     rax, rdi
        xorps   xmm0, xmm0
        movups  xmmword ptr [rdi + 4], xmm0
        mov     dword ptr [rdi], 1
        ret
  • xorps xmm0, xmm0 将 16 字节(或 4 整数)SSE 寄存器 xmm0 设置为 [0,0,0,0]。
  • movups xmmword ptr [rdi + 4], xmm0xmm0 寄存器的所有 4 个整数复制到位置 [rdi + 4],即 ret_array 的元素 1、2、3 和 4。
  • mov dword ptr [rdi], 1 将值 1 移动到 ret_array 的第一个元素。
  • ret_array是在[=25=的位置],[rdi + 4]是在[=27=的位置的元素],[rdi + 8]是在[=29的位置的元素=],等等

如您所见,它仅将其他四个值初始化为 0,然后将第一个值设置为 1。第一个值不会被写入两次。


小提示

如果您将 N 设置为例如8,它确实实际上写了两次值:

example::one_with_length_8:
        mov     rax, rdi
        xorps   xmm0, xmm0
        movups  xmmword ptr [rdi + 16], xmm0
        movups  xmmword ptr [rdi + 4], xmm0
        mov     dword ptr [rdi], 1
        ret

有趣的是,它实际上并没有写两次值[0],而是写了值[4]。它一次写入 [1,2,3,4],然后写入 [4,5,6,7],然后写入 [0]。 但那是因为这是最快的方法。它在 SSE 寄存器中存储 4 个零整数,然后 zero-initializes 向量一次存储 4 个整数。在没有 4-int SSE 命令帮助的情况下,两次写入 int 比初始化其他值更快。

如果您完全手动初始化它,甚至会发生这种情况:

pub fn one_with_length_8() -> [i32; 8] {
    [1,0,0,0,0,0,0,0]
}
example::one_with_length_8:
        mov     rax, rdi
        mov     dword ptr [rdi], 1
        xorps   xmm0, xmm0
        movups  xmmword ptr [rdi + 4], xmm0
        movups  xmmword ptr [rdi + 16], xmm0
        ret

你可以看到顺序不同,但指令是相同的。