Выбрать главу

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The compiler forbids use of uninitialized variables, as this would lead to undefined behavior.

When data is bound by the same name immutably, it also freezes. Frozen data can't be modified until the immutable binding goes out of scope:

fn main() {

let mut _mutable_integer = 7i32;

{

// Shadowing by immutable `_mutable_integer`

let _mutable_integer = _mutable_integer;

// Error! `_mutable_integer` is frozen in this scope

_mutable_integer = 50;

// FIXME ^ Comment out this line

// `_mutable_integer` goes out of scope

}

// Ok! `_mutable_integer` is not frozen in this scope

_mutable_integer = 3;

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Rust provides several mechanisms to change or define the type of primitive and user defined types. The following sections cover:

   • Casting between primitive types

   • Specifying the desired type of literals

   • Using type inference

   • Aliasing types

Rust provides no implicit type conversion (coercion) between primitive types. But, explicit type conversion (casting) can be performed using the as keyword.

Rules for converting between integral types follow C conventions generally, except in cases where C has undefined behavior. The behavior of all casts between integral types is well defined in Rust.

// Suppress all warnings from casts which overflow.

#![allow(overflowing_literals)]

fn main() {

let decimal = 65.4321_f32;

// Error! No implicit conversion

let integer: u8 = decimal;

// FIXME ^ Comment out this line

// Explicit conversion

let integer = decimal as u8;

let character = integer as char;

// Error! There are limitations in conversion rules. A float cannot be directly converted to a char.

let character = decimal as char;

// FIXME ^ Comment out this line

println!("Casting: {} -> {} -> {}", decimal, integer, character);

// when casting any value to an unsigned type, T,

// T::MAX + 1 is added or subtracted until the value

// fits into the new type

// 1000 already fits in a u16

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

// 1000 - 256 - 256 - 256 = 232

// Under the hood, the first 8 least significant bits (LSB) are kept,

// while the rest towards the most significant bit (MSB) get truncated.

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

// -1 + 256 = 255

println!(" -1 as a u8 is : {}", (-1i8) as u8);

// For positive numbers, this is the same as the modulus

println!("1000 mod 256 is : {}", 1000 % 256);

// When casting to a signed type, the (bitwise) result is the same as

// first casting to the corresponding unsigned type. If the most significant

// bit of that value is 1, then the value is negative.

// Unless it already fits, of course.

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

// 128 as u8 -> 128, whose two's complement in eight bits is:

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

// repeating the example above

// 1000 as u8 -> 232

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

// and the two's complement of 232 is -24

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

// Since Rust 1.45, the `as` keyword performs a *saturating cast* when casting from float to int.

// If the floating point value exceeds the upper bound or is less than the lower bound, the returned value will be equal to the bound crossed.

// 300.0 is 255

println!("300.0 is {}", 300.0_f32 as u8);

// -100.0 as u8 is 0

println!("-100.0 as u8 is {}", -100.0_f32 as u8);

// nan as u8 is 0

println!("nan as u8 is {}", f32::NAN as u8);

// This behavior incures a small runtime cost and can be avoided with unsafe methods, however the results might overflow and return **unsound values**. Use these methods wisely:

unsafe {

// 300.0 is 44

println!("300.0 is {}", 300.0_f32.to_int_unchecked::<u8>());

// -100.0 as u8 is 156

println!("-100.0 as u8 is {}", (-100.0_f32).to_int_unchecked::<u8>());

// nan as u8 is 0

println!("nan as u8 is {}", f32::NAN.to_int_unchecked::<u8>());

}

}

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

XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX