How do I declare a static mutable variable without assignment?

 ̄綄美尐妖づ 提交于 2020-02-02 00:24:48

问题


I tried the following

struct mbuf
{
  cacheline: *mut [u64],               // great amount of rows follows below
  // ..........
}
static mut arr: [mbuf; 32];                // Q1 my main aim
// something as before but using Vec;      // Q2 also main aim

fn main() {
 // let static mut arr: [mbuf; 32];        // Q3 also doesn't work
 // static mut arr: [mbuf; 32];            // Q3 also doesn't work
}

and got error

src/main.rs:74:29: 74:30 error: expected one of `+` or `=`, found `;`
src/main.rs:74   static mut arr: [mbuf; 32];
                                           ^

Q1,Q2,Q3 - Is it possible and how?


回答1:


A static or constant must be assigned when declared; they can never be assigned to after that.

A static must be purely literals; it cannot have any function calls.

A constant must at present be purely literals, but when RFC 911, const fn is implemented it will be possible to do things more like how you desire.

Inside a function, you can have static or const items, just as outside a function, and there is no difference—placing items (trait and type definitions, functions, &c.) inside a function purely hides them from the outside scope. Therefore you typically might as well use let foo.




回答2:


You can use lazy-static to initialize the static array on first access, even though it might incur a minimal overhead (it seems to invoke Once::call_once every time you access the static variable).

For example, Cargo.toml:

[package]
name = "arr"
version = "0.0.1"

[[bin]]
name = "arr"
path = "arr.rs"

[dependencies]
lazy_static = "*"

arr.rs:

#[macro_use]
extern crate lazy_static;
use std::mem;
use std::ptr;

#[derive(Debug)]
struct Mbuf {
    cacheline: *mut u64,
}
// Let's pretend it's thread-safe to appease the lazy_static! constrains.
unsafe impl Sync for Mbuf { }

lazy_static! {
    static ref ARR: [Mbuf; 32] = {
        let mut tmp: [Mbuf; 32] = unsafe { mem::uninitialized() };
        for idx in 0..tmp.len() {
            tmp[idx] = Mbuf { cacheline: ptr::null_mut() };
        }
        tmp
    };
}

fn main() {
    println!("{:?}", *ARR);
}

Alternatively, just make your own lazy accessor:

use std::mem;
use std::ptr;

#[derive(Debug)]
struct Mbuf {
    cacheline: *mut u64,
}

static mut ARR: Option<[Mbuf; 32]> = None;
fn arr() -> &'static mut [Mbuf; 32] {
    unsafe {
        if ARR.is_none() {
            let mut tmp: [Mbuf; 32] = mem::uninitialized();
            for idx in 0..tmp.len() {
                tmp[idx] = Mbuf { cacheline: ptr::null_mut() };
            }
            ARR = Some(tmp);
        }
        mem::transmute(ARR.as_mut().unwrap())
    }
}

fn main() {
    println!("{:?}", arr());
}

Needless to say, this code isn't thread-safe and thus shuns some of the Rust safety guarantees, but for a speed comparison port it shall suffice.



来源:https://stackoverflow.com/questions/30145814/how-do-i-declare-a-static-mutable-variable-without-assignment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!