Data Type
type | detail | example |
i8, i16, i32, i64, i128, u8, u16, u32, u64, u128 | i 해당 비트 크기를 갖는 부호 있는 정수 u 해당 비트 크기를 갖는 부호 없는 정수 |
50, -5i8, 0x100u16, 0o100i16, 20_933_684u64, b'a' (u8 바이트 리터럴) |
isize, usize | 머신 주소 크기(32 또는 64비트) | 164, -0b0011_1010isize |
f32, f64 | IEEE754 단정밀도, 배정밀도 부동소수점 | 1.1684, 3.14f32, 6.0221e23f64 |
bool | 불 | true, false |
char | 32비트 크기를 갖는 유니코드 문자 | 'b', '\n', '\7f', '\u{CA1}', '準' |
(char, u8, i32) | 혼합 가능한 튜플 | ('%', 0x7f, -1) |
() | 유닛(빈 튜블) | () |
struct S {x: f32, y: f32} | 이름 있는 필드로 된 구조체 | S { x:119.0, y: 200.0 } |
struct T (i32, char); | 튜플형 구조체 | T(100, 'X') |
struct E; | 필드를 갖지 않는 유닛형 구조체 | E |
enum Attend { OnTime, Late(u32) } | 열거, 대수적 데이터 타입 | Attend::Late(5), Attend::OnTime |
Box<Attend> | 박스: 힙에 있는 값의 소유권을 갖는 포인터 | Box::new(Late(15)) |
&i32, &mut i32 | 공유된 레퍼런스와 변경할 수 있는 레퍼런스, 참조 대상보다 더 오래 지속될 수 없는 소유권을 갖지 않는 포인터 | &s.y, &mut v |
String | 동적 크기를 갖는 문자열 | "배고파".to_string() |
&str | str 레퍼런스: 소유권을 갖지 않는 텍스트 포인터 | "필승정예공군".&s[0..2] |
[f64; 4], [u8; 256] | 요소의 타입이 모두 같은 고정 길이 배열 | [1.0, 0.0, 0.0, 1.0], [b' '; 256] |
Vec<f64> | 요소의 타입이 모두 같은 가변 길이 벡터 | vec![0.123, 0.456, 0.789] |
&[u8], &mut [u8] | 슬라이스 레퍼런스: 배열이나 벡터의 일부분을 참조하는 레퍼런스 | &v[10..20], &mut a[..] |
Option<&str> | 옵션값: None(없음), Some(v) (있음, 값은 v) | Some("Ph."), None |
Result<u64, Error> | 실패할 수도 있는 작업 결과 : 성공값 Ok(v), 오류값 Err(e) | Ok(4096), Err(Error::last_os_error()) |
&dyn Any, &mut dyn Read | 트레이드 객체: 주어진 메서드 집합을 구현하고 임의의 값을 참조하는 레퍼런스 | value as &dyn Any, &mut file as &mut dyn Read |
fn(&str) -> bool | 함수 포인터 | str::is_empty |
클로저 타입은 기록 혀앹를 갖지 않는다 | 클로저 | |a, b| { a*a | b*b } |
정수형 오버플로우 처리
정수형 자료형의 주의점 (release시 충분히 정수 오버플로우가 발생할 수 있다.)
디버그 모드에서 정수 오버플로우가 발생하면 panic을 발생시키는 검사를 포함하지만, release 모드로 컴파일 할 경우 검사가 실행파일에 포함되지 않음. two's complement wrapping을 통해 wrap around를 거친다.
표준 라이브러리에서 아래 메서드를 사용 할 수 있다.
- wrapping_add와 같은 wrapping_* 메서드로 감싸기 동작 실행하기
// 첫 번째 곱은 u16로 표현 가능 // 두 번째 곱은 그럴 수 없으므로 250000을 2^16로 나눈 나머지 산출 assert_eq!(100_u16.wrapping_mul(200), 20000); assert_eq!(500_u16.wrapping_mul(500), 53392); // 부호있는 타입을 대상으로 하는 연산은 음숫값으로 순환되기도 함 assert_eq!(500_i16.wrapping_mul(500), -12144); // 쉬프트는 이동거리가 값이 크기 안에 들어가도록 순환 // 16비트 타입일 때 17비트 쉬프트는 1비트 쉬프트와 같은 역할 assert_eq!(5_i16.wrapping_shl(17), 10);
- checked_* 메서드를 사용하여 오버플로우가 발생하면 None 값 반환하기
// 10과 20의 합은 u8로 표현할 수 있다. assert_eq!(10_u8.checked_add(20), Some(30)); // 하지만 100과 200의 합은 그럴 수 없다. assert_eq!(100_u8.checked_add(200), None); // 덧셈을 하는데 오버플로우가 발생하면 패닉에 빠진다. let sum = x.checked_add(y).unwrap(); // 이상하지만 부호 있는 나눗셈도 오버플로우를 일으킬 수 있다. // 부호 있는 n비튼는 -2^n-1은 표현하지만 2^n-1은 표현 할 수 없다. assert_eq!((-128_i8.checked_div(-1), None);
- overflowing_* 메서드를 사용하여 값과 함께 오버플로우 발생이 있었는지를 알려주는 부울린 값 반환하기
// overflowing은 (result, overflowed) 튜플 반환, result는 반환 값, overflowed는 발생 여부 bool assert_eq!(255_u8.overflowing_sub(2), (253, false)); assert_eq!(255_u8.overflowing_add(2), (1, true)); assert_eq!(5_u16.overflowing_shl(17), (10, true));
- saturating_* 메서드를 사용하여 값의 최대 혹은 최솟값 사이로 제한하기
// 표현할 수 있는 값 중 수학적으로 옳은 결과에 가장 가까운 값을 반환 assert_eq!(32760_i16.staurating_add(10), 32767); assert_eq!((-32760_i16).saturating_sub(10), -32768);
checked_*, wrapping_*, saturating_*, overflowing_* 뒤에 붙은 * 접미사엔 연산을 넣는다.
접미사 | 예시 |
add | 100_i8.checked_add(27) == Some(127) |
sub | 10_u8.checked_sub(11) == None |
mul | 128_u8.saturaing_mul(3) == 255 |
div | 64_u16.wrapping_div(8) == 8 |
rem | (-32768_i16).wrapping_rem(-1) == 0 |
neg | (-128_i8).checked_neg() == None |
abs | (-32768_i16).wrapping_abs() == -32768 |
pow | 3_u8.checked_pow(4) == Some(81) |
shl | 10_u32.wrapping_shl(34) == 40 |
shr | 40_u64.wrapping_shr(66) == 10 |
대리 표기법으로만 사용 가능한 문자들
문자 | 바이트 리터럴 | 수칫값 |
' (작은 따음표) | b'\'' | 39u8 |
\ (백슬래시) | b'\\' | 92u8 |
새 줄 | b'\n' | 10u8 |
캐리지 리턴 | b'\r' | 13u8 |
탭 | b'\t' | 9u8 |
ref. https://rinthel.github.io/rust-lang-book-ko/ch03-02-data-types.html
'Coding > Rust' 카테고리의 다른 글
[Rust] 러스트 실행 시간 (코드 동작시간) 측정 (0) | 2024.05.25 |
---|---|
[Rust] 러스트 바이너리 파일 크기 줄이기 (0) | 2024.05.24 |
[Rust] 러스트 출력 포맷팅 (Formatted print) 예시 (1) | 2024.05.23 |