Rust's type system is strict. Integers can also specify the number of bits from i8 to i128, and one character of a string contains the entire Unicode code point in one char. In this episode, we look at scalar types (integer, real number, bool, char) and complex types (tuple, array).
Learning Objectives
- The number of bits and presence or absence of sign of integer type are used separately.
- Understand the basic operations of
f32/f64,bool, andchar. - Learn the definition, access, and decomposition grammar of tuples and arrays.
- I know that the “byte length” and “number of characters” of Korean strings are different.
Key concepts
| sign | bit 8 | 16 | 32 (default) | 64 | 128 | pointer width |
|---|---|---|---|---|---|---|
| Yes | i8 |
i16 |
i32 |
i64 |
i128 |
isize |
| None | u8 |
u16 |
u32 |
u64 |
u128 |
usize |
-
The default integer literal is
i32, and the real number isf64. -
usize/isizeis determined according to the pointer width (32/64 bit) and is used for length and index. -
Panic overflow in debug build, wrapping in release build. If intentional wrapping is needed, use a method such as
wrapping_add. -
f32(single precision),f64(double precision, default). -
There is no automatic conversion of integer/real-number-is, so explicit casting
as:let f = i as f64; -
When comparing floating decimal numbers, the
(a - b).abs() < EPSpattern is safer than equality.
3) bool and char
-
boolis two values:true/false. -
charis a 4-byte value containing a single quote and one Unicode scalar.charwith both Korean and emoji. -
Strings (
&str/String) are enclosed in double quotation marks.s.len()is number of bytes,s.chars().count()is number of characters. -
Tuple
(T1, T2, ...): a bunch of different types, fixed length. The indices are.0,.1. -
Array
[T; N]: Fixed-length bundle of the same type. The index isarr[0]. The length isarr.len(). -
If dynamic length is required, go to
Vec<T>after the next part.
See as example
//+3%ED%8E%B8+%EC%98%88%EC%A0%9C+1:+%EC%A0%95%EC%88%98%C2%B7%EC%8B%A4%EC%88%98%C2%B7b ool
fn main() {
//+%EC%A0%95%EC%88%98+%ED%83%80%EC%9E%85%EC%9D%80+i+/+u+++%EB%B9%84%ED%8A%B8+%EC%88 %98:+i8,+i16,+i32(%EA%B8%B0%EB%B3%B8),+i64,+i128,+isize
//+%EB%B6%80%ED%98%B8+%EC%97%86 %EB%8A%94+%EC%A0%95%EC%88%98%EB%8A%94+u8+~+u128,+usize.
let signed: i32 = -42;
let unsigned: u64 = 100_000_000;
let pointer_size: usize = 1024; //+%EB%B0%B0%EC%97%B4/%EB%B2%A1 %ED%84%B0+%EA%B8%B8%EC%9D%B4+%ED%91%9C%ED%98%84%EC%97%90+%EC%82%AC%EC%9A%A9
println!("i32 = {signed}");
println!("u64 = {unsigned}");
println!("usize= {pointer_size}");
//+%EC%8B% A4%EC%88%98+%ED%83%80%EC%9E%85%EC%9D%80+f32,+f64(%EA%B8%B0%EB%B3%B8)
let pi: f64 = 3.141_592_653_589_793;
let half = 0.5_f32;
println!("pi = {pi}");
println!("half = {half}");
//+%EC%82%B0%EC%88 %A0+%EC%97%B0%EC%82%B0%EC%9E%90:+++-+*+/+%
//+%EC%A0%95%EC%88%98+%EB%82%98%EB%88%97%EC% 85%88%EC%9D%80+%EB%B2%84%EB%A6%BC+(%EC%86%8C%EC%88%98%EC%A0%90+%EB%B2%84%EB%A0%A4%EC%A7%90)
let div = 7 / 2; // 3
let rem = 7 % 2; // 1
let fdiv = 7.0 / 2.0; // 3.5
println!("7/2 = {div}, 7%2 = {rem}, 7.0/2.0 = {fdiv}");
// bool — true / false
let on: bool = true;
let off = !on;
println!("on = {on}, off = {off}");
}
//Part 3 Example 2: char is a Unicode scalar character (4 bytes)
fn main() {
let a: char = 'A';
let han: char = 'Han';
let emoji: char = '🦀';
let escape: char = '\n';
println!("ASCII : {a}");
println!("Hangul: {han}");
println!("Emoji: {emoji}");
println!("The newline escape character is also char: {}", escape as u32);
//char is a single quote, a string (`
let s: &str = "hello";
println!("String: {s}, Byte Length: {}", s.len());
//⚠️ s.len() is the length in “bytes”. One Korean character usually takes 3 bytes.
println!("Number of characters: {}", s.chars().count());
}
//Part 3 Example 3: Tuples and Arrays
fn main() {
//Tuple: Fixed-length collection that can group different types
let point: (i32, i32, &str) = (3, 5, "origin");
//Index access is `.0`, `.1` ...
println!("x = {}, y = {}, name = {}", point.0, point.1, point.2);
//Destructuring
let (x, y, name) = point;
println!("Decomposition: {x}, {y}, {name}");
//Array: Fixed-length collection of the same type [T; N]
let scores: [u32; 5] = [80, 90, 75, 100, 60];
println!("First score: {}", scores[0]);
println!("Number of scores: {}", scores.len());
//Fill with same value: [value; Number]
let zeros = [0u8; 4];
println!("zeros = {:?}", zeros);
}
Common Mistakes
A: No. Rust does not automatically convert between integers. Casting as (x as i64) must be specified where required. Careless narrowing conversions can result in loss of information, so the compiler prevents them.
A. The behavior is different: panic in debug builds and wrapping in release builds. If the intention is wrapping, use an explicit method such as wrapping_add, and if detection is necessary, use checked_add (Option) or overflowing_add (tuple).
A. len() returns UTF-8 number of bytes. One Korean character is usually 3 bytes, so two characters are 6. If you need the number of characters, use chars().count(). (Graphics graphime is more complex, but for beginners, chars() is sufficient.)
A. You need to know at compile time. For collections whose size changes at runtime, use Vec<T>. (Module/Vec will be covered in detail in a later lesson.)
Cleanup
iN/uNfor integers,f32/f64for real numbers, andi32andf64for basic heuristics.- Conversion between types is not automatic, but explicit casting (
as). - Note that
charis one Unicode character and&str.len()is the number of bytes. - The tuple is a heterogeneous bundle
(T1, T2, ...), and the array is a homogeneous fixed length[T; N].
Try it yourself
Solve the assignment below. The reference solution is shown below.