Ржавеем по полному! #3. Функции и указатели.
Сегодня познакомимся с функциями и указателями, а также по мелочи: зоны видимости.
Функции
Функции в расте похожи на функции в Си, Jawa, луа. Для создания функции используется ключевое слово fn.
fn add(a: i32, b: usize) -> usize { a + b}
После ключевого слова fn идет имя функции, далее в скобках указываются аргументы через запятую, и опционально, стрелочка -> и возвращаемый тип.
Указывая аргументы нужно указывать тип аргумента после символа :.
Функции в которых не указано возвращаемое значение, возвращают ()
Ключевое слово return возвращает значение из функции.
fn answer() -> i32 { return 42;}
return не всегда обязателен, позже разберемся где он нужен, а где не нужен.
Указатели
Указатели в расте гораздо безопаснее чем указатели в Си. Создать указатель на неизменяемые данные можно при помощи &.
let a = 10;let pa = &a;
Получить значение из указателя можно при помощи символа *.
let a = 10;let pa = &a;println!("a = {}; *pa = {}; a + a = {}; *pa + *pa = {}", a, *pa, a + a, *pa + *pa);// \--> a = 10; *pa = 10; a + a = 20; *pa + *pa = 20
Но в некоторых случаях писать * не обязательно.
let a = 10;let pa = &a;println!("a = {}; pa = {}; a + a = {}; pa + pa = {}", a, pa, a + a, pa + pa);// \--> a = 10; pa = 10; a + a = 20; pa + pa = 20
Раст сам все поймет, за что ему спасибо.
Иногда мы хотим создать изменяемую ссылку. Для этого используется &mut.
let mut a = 10;let pa = &mut a;*pa += 1; // здесь * обязателен println!("{}", pa); //--> 11
Если мы хотим изменить значение на которое указывает наш указатель, * обязателен. Без него раст не может понять, мы хотим присвоить новый указатель, или значение.
В расте используется концепция "либо один писатель, либо много читателей". В примере выше, переменную a прочитать мы уже не сможем, и писать в нее тоже не сможем, так как она передана указателю pa. pa – писатель.
Бывают случаи когда мы хотим присвоить указателю новое значение, то есть сделать так, что бы указатель указывал на другие данные. Это тоже предусмотрено.
let mut a = 10;let mut b = 20;let mut pa = &mut a; println!("{}", pa); // --> 10 pa = &mut b; println!("{}", pa); // --> 20 println!("{}", a); // --> 10// ^ ошибка, a уже имеет писателя, читателя не создать. println!("{}", &a); // --> 10// ^- ошибка, a уже имеет писателя, читателя не создать. println!("{}", &mut a); // --> 10// ^----- ошибка, a уже имеет писателя, еще одного не создать.
Как видите, все правила про "либо один писатель, либо много читателей" работают даже если на a уже не указывает ничего.
Зоны видимости
Зоны видимости в расте ничем не отличаются от тех же в Луа.
fn main() { let a = 10; { let b = 20; println!("{}", a); // --> 10 println!("{}", b); // --> 10 } println!("{}", a); // --> 10 println!("{}", b); // --> 10 // ^ ошибка, b нет.}
Хочу отметить только, что в расте все переменные удаляются когда уйдут из зоны видимости. Исключением являются только значения которые возвращаются в функциях.
На сегодня все. Извините что запоздал с 3 частью, так уж вышло. В следующий раз познакомимся с перечеслениями (enum) и структурами (struct). =)
- 4
7 комментариев
Рекомендуемые комментарии