형변환
러스트는 기본 타입 간 암묵적 형변환 기능을 제공하지 않습니다.
형변환은 as
키워드를 사용해 명시적으로 수행해야 합니다.
정수 타입 간의 형변환 규칙은 일반적으로 C언어 규칙을 따릅니다. (C언어에서 동작하지만 정의되지 않은 동작(UB)인 경우는 제외됩니다.) 정수 타입 간 형변환은 모두 러스트에 잘 정의되어 있습니다.
// 오버플로우 형변환 경고를 모두 숨깁니다. #![allow(overflowing_literals)] fn main() { let decimal = 65.4321_f32; // 에러! 암묵적 형변환은 불가능합니다 let integer: u8 = decimal; // 고쳐주세요! ^ 이 줄을 주석 처리해주세요 // 명시적 형변환 let integer = decimal as u8; let character = integer as char; // 에러! 변환 규칙에는 제한이 존재합니다. // 부동 소수점 타입은 char 타입으로 직접 변환할 수 없습니다. let character = decimal as char; // 고쳐주세요! ^ 이 줄을 주석 처리해주세요 println!("형변환: {} -> {} -> {}", decimal, integer, character); // 어떤 값을 부호 없는 타입 T로 형변환 할 경우, // 값을 새로운 타입에 저장 할 수 있을때까지 // T::MAX + 1 을 더하거나 뺍니다. // 1000은 u16 타입으로 저장할 수 있습니다 println!("1000 as u16 = {}", 1000 as u16); // 1000 - 256 - 256 - 256 = 232 // 내부적으로, 처음 8개 최하위 비트(LSB)는 유지되고, // 최상위 비트(MSB) 방향의 나머지는 잘립니다. println!("1000 as u8 = {}", 1000 as u8); // -1 + 256 = 255 println!(" -1 as u8 = {}", (-1i8) as u8); // 양수의 경우, 나머지 연산 결과와 동일합니다 println!("1000 % 256 = {}", 1000 % 256); // 부호 있는 타입으로 형변환 할 경우, // (비트 단위) 결과는 부호 없는 타입으로 형변환한 것과 같습니다. // 만약 값의 최상위 비트(MSB)가 1일 경우, 해당 값은 음수입니다. // 물론, 바로 저장 가능한 경우는 제외고요. println!(" 128 as i16 = {}", 128 as i16); // 128 as u8 -> 128, 8비트 상에서 2의 보수: println!(" 128 as i8 = {}", 128 as i8); // 앞선 예시 반복 // 1000 as u8 -> 232 println!("1000 as u8 = {}", 1000 as u8); // 232에 대한 2의 보수는 -24입니다 println!(" 232 as i8 = {}", 232 as i8); // 러스트 1.45 버전부터, `as` 키워드는 부동 소수점을 정수로 형변환 할 경우 // *포화 연산(saturate cast)*를 수행합니다. // 부동 소수점 값이 상한을 초과하거나 하한보다 작을 경우, // 반환 값은 한계치와 동일합니다. // 300.0 = 255 println!(" 300.0 = {}", 300.0_f32 as u8); // -100.0 as u8 = 0 println!("-100.0 as u8 = {}", -100.0_f32 as u8); // nan as u8 = 0 println!(" nan as u8 = {}", f32::NAN as u8); // 포화 연산은 약간의 런타임 비용이 발생합니다. // unsafe 메소드로 포화 연산을 회피할 수 있지만, 오버플로우가 발생해 // **부적절한** 결과 값이 반환될 수 있으므로 사용에 주의해야 합니다. unsafe { // 300.0 = 44 println!(" 300.0 = {}", 300.0_f32.to_int_unchecked::<u8>()); // -100.0 as u8 = 156 println!("-100.0 as u8 = {}", (-100.0_f32).to_int_unchecked::<u8>()); // nan as u8 = 0 println!(" nan as u8 = {}", f32::NAN.to_int_unchecked::<u8>()); } }