Немного о static

в 17:22, , рубрики: Rust, Программирование

Чуть-чуть о статье

Теперь попробуем создать что-то вроде «глобальной переменной» с помощью ключевого слова static.

«Они похожи на постоянные, но статические значения не встраиваются в место их использования. Это значит, что каждое значение существует в единственном экземпляре, и у него есть определённый адрес».

Объявим её:
static N = 8;

fn main() {
		println!("N = {}",N);
}

Компилируем. Выход:

error: expected ':', found '='
static N = 8;
~~~~~~~^

Как видно, нам и в этом случае необходимо указывать тип. Исправляем:

static N: i32 = 8;

И у нас всё в порядке. Выход:

N = 8

Пробуем так:

static N: i32 = 4;
static N: i32 = 5;

fn main() {
	println!("N = {}",N);
}

Выход:

error: duplicate definition of value `N` [E0428]

Так же как и с константами. Ясно. Продолжаем делать всё, что делали с константами:

static N: i32 = 4;
fn main() {
    println!("N = {}",N);
    static N: i32 = 8;
    println!("N = {}",N);
}

Выход:

warning: static item is never used: `N`, #[warn(dead_code)] on by default
static N: i32 = 4;
^~~~~~~~~~~~~~~~~

Так же как и с константами. Пробуем дальше:

static N: i32 = 4;
fn main() {
    println!("N = {}",N);
    static N: i32 = 8;
    println!("N = {}n",N);
    other();
}

fn other() {
    println!("N = {}",N);
}

Выход:

N = 8
N = 8

N = 4

Далее:

static N: i32 = 4;
fn main() {
    println!("N = {}",N);
    static M: i32 = 8;
    println!("M = {}n",M);
    other();
}


fn other() {
    println!("N = {}",N);
}

То выход будет таким:

N = 4
M = 8

N = 4

И ещё один эксперимент:

fn main() {
    println!("N = {}",N);
    static N: i32 = 8;
    static N: i32 = 9;
    println!("N = {}n",N);
}

Выход:

error: duplicate definition of value `N` [E0428]
static N: i32 = 9;
^~~~~~~~~~~~~~~~~

Следующий:

fn main() {
    println!("N = {}",N);
    static N: i32 = 8;
	{
    	static N: i32 = 9;
	}   
    println!("N = {}n",N);
}

Выход:

N = 8
N = 8

Можно и так:

fn main() {
    println!("N = {}",N);
    static N: i32 = 8;
	{
    	println!("N = {}n",N);
	}   
    println!("N = {}n",N);
}

Выход:

N = 8
N = 8

N = 8

А если так:

fn main() {
    println!("N = {}",N);
	{
    	static N: i32 = 8;
    	println!("N = {}n",N);
	}   
    println!("N = {}n",N);
}

Выход:

error: unresolved name `N` [E0425]
println!(«N = {}»,N);
~~~~~~~~~~~~^
...

Ещё:

static N: i32 = 3;

fn main() {
    println!("N = {}",N);
	{
    	static N: i32 = 8;
    	println!("N = {}n",N);
	}   
    println!("N = {}n",N);
}

Выход:

N = 3
N = 8

N = 3

Короче, здесь всё было как с константами. Попробуем сделать переменную изменяемой:

fn main() {
		println!("{} = n",N);
		static mut N: i32 = 8;
}

Выход:

error: use of mutable static requires unsafe function or block [E0133]
println!("{} = N",N);

Говорит, типо, это слишком небезопасно.

«По скольку N изменяемо, один поток может изменить его во время того, как другой читает его значение. Это ситуация «гонки» по данным, и она считается небезопасным поведением в Rust. Поэтому и чтение, и изменение статическ ого изменяемого зна чения( static mut ) является небезопасным (unsafe), и обе эти операции должны выполняться в небезопасных блоках ( unsafe block)».

Поэтому делаем так:

fn main() {
		unsafe {
			println!("{} = N",N);
		}
		static mut N: i32 = 8;
}

Выход:

8 = N

Можем сделать так:

fn main() {
		unsafe {
			println!("{} = n",N);
			static mut N: i32 = 8;
		}
		println!("{} = n",N);
}

Но тогда N не будет видно для второго println!(...). Нам вернут ошибку:

error: unresolved name 'N' [E0425]
println!("{} = N",N);

Если сделать её глобальной, то работает:

static mut N: i32 = 8;
fn main() {
		unsafe {
			println!("{} = n",N);
		}
		
}

Выход:

8 = N

Теперь ссылки.

«Каждое значение существует в единственном экземпляре, и у него есть определённый адрес. Статические зна чения живут в течение всего времени работы программы, и любая ссылка
на постоянную имеет статическ ое время жизни ( static lifetime)».

static N: i32 = 8
fn main() {
    let x = &N;
    println!("{} = N",N);
    println!("{} = N",*x);
    println!("{:p} -> N",&N);
    println!("{:p} -> N",x);
}

Выход:

N = 8
N = 8
0x8010b884 -> N
0x8010b884 -> N

Ну, там ещё есть такое:

«Более того, любой тип, хранимый в статическ ой переменной, должен быть ограничен
Sync и не может иметь реализации Drop ».

Но я не знаю что это значит и буду очень рад, если кто-то зкажет, что это значит…

Литература:

The Rust Reference (английский)
The Rust Programming Language (английский)
The Rust Programming Language (русский)

Автор: no_face

Источник

Поделиться новостью

* - обязательные к заполнению поля