Rust на примерах — страница 10 из 65

// 128 as u8 -> 128, дополнительный код которого в 8 битах:

println!(" 128 as a i8 is : {}", 128 as i8);

// повторяем примеры

// 1000 as u8 -> 232

println!("1000 as a i8 is : {}", 1000 as i8);

// и дополнительный код 232 - это -24

println!(" 232 as a i8 is : {}", 232 as i8);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Литералы

Числовые литералы могут быть обозначены добавлением типа в качестве суффикса. Например, чтобы указать, что литерал 42 должен иметь тип i32, необходимо написать 42i32.

Тип литералов без суффикса будет зависеть от того, как они используются. Если нет никаких ограничений, то компилятор будет использовать i32 для целочисленных литералов, а f64 для литералов с плавающей точкой.

fn main() {

// Литералы с суффиксами. Их тип известен при инициализации.

let x = 1u8;

let y = 2u32;

let z = 3f32;

// Литералы без суффиксов. Их тип будет зависеть от того, как их используют.

let i = 1;

let f = 1.0;

// `size_of_val` возвращает размер переменной в байтах

println!("size of `x` in bytes: {}", std::mem::size_of_val(&x));

println!("size of `y` in bytes: {}", std::mem::size_of_val(&y));

println!("size of `z` in bytes: {}", std::mem::size_of_val(&z));

println!("size of `i` in bytes: {}", std::mem::size_of_val(&i));

println!("size of `f` in bytes: {}", std::mem::size_of_val(&f));

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

В предыдущем коде используются некоторые вещи, которые не были объяснены ранее. Вот краткое объяснение для нетерпеливых читателей:

   • fun(&foo) используется для передаче аргумента в функцию по ссылке, вместо передачи по значению (fun(foo)). Подробнее см. заимствование или соответствующую главу в книге.

   • std::mem::size_of_val является функцией, но вызывается с указанием полного пути. Код можно разделить на логические единицы, называемые модулями. В данном случае, функция определена в модуле mem, а модуль mem определён в контейнере std. Подробнее см. модули и контейнеры, а так же соответствующую главу в книге

Вывод типов

Движок вывода типов весьма умён. Он делает куда больше, чем просто смотрит на тип r-value при инициализации. Он также смотрит, как используется значение после инициализации, чтобы вывести его тип. Вот расширенный пример вывода типов:

fn main() {

// Благодаря выведению типов компилятор знает, `elem` имеет тип - u8.

let elem = 5u8;

// Создадим пустой вектор (расширяемый массив).

let mut vec = Vec::new();

// В данном месте компилятор не знает точный тип `vec`, он лишь знает,

// что это вектор чего-то там (`Vec<_>`).

// Добавляем `elem` в вектор.

vec.push(elem);

// Ага! Теперь компилятор знает, что `vec` - это вектор, который хранит в себе тип `u8`

// (`Vec`)

// ЗАДАНИЕ ^ Попробуйте закомментировать строку `vec.push(elem)`

println!("{:?}", vec);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Не потребовалось никакой аннотации типов переменных, компилятор счастлив, как и программист!

Псевдонимы

Оператор type используется, чтобы задать новое имя существующему типу. Имя типа должно быть в стиле UpperCamelCase, иначе компилятор выдаст предупреждение. Исключением являются примитивные типы: usize, f32 и другие.

// `NanoSecond` это новое имя для `u64`.

type NanoSecond = u64;

type Inch = u64;

// Используйте этот атрибут, чтобы не выводить предупреждение

// о именах не в стиле CamelCase

#[allow(non_camel_case_types)]

type u64_t = u64;

// ЗАДАНИЕ ^ Попробуйте удалить атрибут

fn main() {

// `NanoSecond` = `Inch` = `u64_t` = `u64`.

let nanoseconds: NanoSecond = 5 as u64_t;

let inches: Inch = 2 as u64_t;

// Обратите внимание, что псевдонимы *не предоставляют* никакой

// дополнительной безопасности типов, так как *не являются* новыми типами

println!("{} nanoseconds + {} inches = {} unit?",

nanoseconds,

inches,

nanoseconds + inches);

}

הההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההההה

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Основное применение псевдонимов — сокращение размера кода: например, тип IoResult является псевдонимом типа Result.

Смотрите также:

Атрибуты

Приведение типов

Примитивные типы могут быть сконвертированы в другие при помощи приведения типов.

Rust предоставляет преобразование между пользовательскими типами (такими как, struct и enum) через использование трейтов. Общие преобразования используют трейты From и Into. Однако есть и конкретные трейты для более частных случаев, например для конвертации String.

FromиInto

Типажи From и Into связаны по своей сути, и это стало частью их реализации. Если вы можете конвертировать тип А в тип В, то будет легко предположить, что мы должны быть в состоянии конвертировать тип В в тип А.