홈강좌Rust 입문·중급 47편 중 5편째
Rust 정수 타입 — i32 가 기본이고, 담을 수 있는 범위가 정해져 있다
Rust 정수는 크기와 부호에 따라 i8~i128, u8~u128 로 나뉘고, 타입을 적지 않으면 i32 가 된다. 타입마다 담을 수 있는 범위가 정해져 있다. 범위를 넘는 숫자를 쓰면 컴파일러가 미리 막고, 실행 중에 넘치면 디버그 빌드에서는 프로그램이 멈춘다.
01 정수 타입은 이름에 규칙이 있다
이름의 첫 글자와 숫자만 보면 된다.
i는 음수도 담는 정수,u는 0 이상만 담는 정수다.- 뒤의 숫자는 크기(비트 수)다. 8·16·32·64·128 이 있다.
| 타입 | 크기 | 쓰는 때 |
|---|---|---|
i32 | 32비트 | 따로 정할 이유가 없을 때. 타입을 안 적으면 이것이다 |
u8 | 8비트 | 0~255 로 충분한 작은 값 |
i64 · u64 | 64비트 | 아주 큰 값 |
usize | 컴퓨터마다 다름 | 배열의 길이·번호 (9편) |
변수 이름 뒤에 : 타입 을 쓰면 타입을 직접 정한다. let age: u8 = 30; 처럼 쓴다.
02 타입마다 담을 수 있는 범위가 다르다
i8::MIN 은 "i8 의 가장 작은 값" 이다. :: 는 "그 타입에 딸린 것" 이라는 표시다. 네 타입의 범위를 찍어 보자. println! 의 {} 는 뒤에 쉼표로 적은 값이 차례로 들어가는 자리다.
fn main() {
println!("i8: {} ~ {}", i8::MIN, i8::MAX);
println!("u8: {} ~ {}", u8::MIN, u8::MAX);
println!("i32: {} ~ {}", i32::MIN, i32::MAX);
println!("u32: {} ~ {}", u32::MIN, u32::MAX);
} Compiling ints v0.1.0 (~/projects/ints)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
Running `target/debug/ints`
i8: -128 ~ 127
u8: 0 ~ 255
i32: -2147483648 ~ 2147483647
u32: 0 ~ 4294967295u8 은 0~255, i32 는 약 -21억~21억이다. 비트 수가 같으면 i 와 u 가 담는 개수는 같다. i 는 그 절반을 음수에 쓸 뿐이다.
03 범위를 넘는 숫자는 컴파일러가 막는다
나이를 u8 로 정해 놓고 300 을 넣어 보자.
fn main() {
let age: u8 = 300;
println!("{age}");
}error: literal out of range for `u8`
--> src/main.rs:2:19
|
2 | let age: u8 = 300;
| ^^^
|
= note: the literal `300` does not fit into the type `u8` whose range is `0..=255`
= note: `#[deny(overflowing_literals)]` on by default- 무엇 — 숫자(literal)가
u8의 범위를 벗어났다. - 어디 — 2번째 줄의
300. - 고치는 법 —
note:가 이유를 적어 준다. 300 은0..=255(0부터 255까지)에 들어가지 않는다. 값을 줄이거나u16처럼 더 큰 타입을 쓴다.
이번에는 255 에 1 을 더한다. 계산 결과가 넘친다.
fn main() {
let level: u8 = 255;
let next = level + 1;
println!("{next}");
}error: this arithmetic operation will overflow
--> src/main.rs:3:16
|
3 | let next = level + 1;
| ^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
|
= note: `#[deny(arithmetic_overflow)]` on by default컴파일러가 계산을 미리 해 보고 u8::MAX + 1, 즉 256 이 된다고 알려 준다. 두 오류 모두 error[E…] 같은 번호가 없다. 대신 #[deny(…)] 표시가 있다. 이 검사는 기본으로 오류(deny)로 정해져 있다는 뜻이다. 경고(warn)로 정해진 검사도 있는데, 3편의 안 쓰는 mut 가 #[warn(unused_mut)] 였다.
값이 실행 중에 정해지면(사용자가 입력한 숫자 같은 것) 컴파일러는 미리 알 수 없다. 그때 넘치면 cargo run 으로 만든 디버그 빌드는 그 자리에서 프로그램을 멈춘다(패닉). 조용히 틀린 값으로 넘어가지 않는다.
04 실습 — 정수끼리 나누면 몫만 남는다
피자 7조각을 두 사람이 나눈다.
fn main() {
let total = 7;
let people = 2;
println!("{}", total / people);
println!("{}", total % people);
} Compiling ints v0.1.0 (~/projects/ints)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.16s
Running `target/debug/ints`
3
1정수끼리 나누면(/) 소수점 아래를 버리고 몫 3 만 남는다. % 는 나머지다. 7 을 2 로 나누면 나머지가 1 이다. 3.5 가 필요하면 실수를 써야 한다. 다음 편에서 실수와, 정수를 실수로 바꾸는 as 를 다룬다.