데이터 타입#
Rust의 모든 값은 Data type을 가집니다.
Rust는 정적 타입 언어이기 때문에 컴파일 시점에 Data type이 정해져 있어야 합니다.
1. Scalar type#
Scalar type은 값 하나를 표현하며 다음 4종류의 Scalar type이 있습니다.
1.1 integer#
integer는 정수를 사용하는 type이며 소수점은 사용할 수 없습니다.
integer type의 종류는 다음 표와 같습니다.
| Size | Signed | Unsigned |
|---|---|---|
| 8-bit | i8 | u8 |
| 16-bit | i16 | u16 |
| 32-bit | i32 | u32 |
| 64-bit | i64 | u64 |
| 128-bit | i128 | u128 |
| arch | isize | usize |
여기서, i는 부호 있는(Signed) 정수로 양수와 음수를 사용할 수 있습니다.u는 부호 없는(Unsigned) 정수로 양수만 사용할 수 있습니다.
Signed는 1-Bit를 부호로 사용하기 때문에 값의 표현 범위가 Unsigned보다 작습니다.
값의 표현 범위는 다음 수식처럼 계산할 수 있으며, $n$은 사용 비트 수를 의미합니다.
- Signed : $-(2^{n-1})$ 부터 $2^{n-1}-1$ 까지
- Unsigned : 0 부터 $2^{n}-1$ 까지
예를 들어, i8은 $-(2^{7})=-128$ 부터 $2^{7}-1=127$ 까지의 값을 사용할 수 있고,u8은 $0$ 부터 $2^{8}-1=255$ 까지의 값을 사용할 수 있습니다.
arch는 컴퓨터가 32-bit Architecture이면 32-bit를 사용하고, 64-bit Architecture이면 64-bit를 사용합니다.
※ Integer overflow
값의 표현 범위를 넘어가면 다음의 2가지 경우가 발생합니다.
- Debug mode : Panic 발생하여 프로그램이 종료 됩니다. (예를 들어,
u8변수에 256을 저장하면 Panic 발생합니다.) - Release mode : 값 표현 범위의 최소값으로 지정됩니다. (예를 들어,
u8변수에 256을 저장하면 overflow 되어 0이 됩니다.)
1.2 floating-point#
Rust에서 소수점을 가지는 실수를 표현하기 위하여 Floating point type을 사용합니다.
Floating point type은 32-bit 크기를 가지는 f32 와 64-bit 크기를 가지는 f64가 있습니다.
다음 코드처럼 Type을 명시하지 않는 경우 기본적으로 f64로 지정됩니다.
let apple = 1.234; // f64
만일, f32를 사용하기 위해 다음 코드와 같이 `:f32’로 명시해야 합니다.
let apple:f32 = 1.234; // f32
1.3 boolean#
Boolean type은 true 또는 false만 가질 수 있으며, 1 byte 크기입니다.
다음 코드와 같이 Boolean type 변수를 생성할 수 있습니다.
let apple = true;
let apple:bool = true;1.4 char#
char는 문자 하나를 표현하는 Type 이며, 작은 따옴표('a')를 사용합니다.
※ 큰 따옴표("a")를 사용하면 문자열 입니다. char가 아닙니다.
Rust의 char는 유니코드 스칼라값으로 4-byte 크기이며 다국어 및 이모지 문자를 저장할 수 있습니다.
※ C/C++ 언어의 1-byte 크기인 char 와 혼돈하지 마세요.
다음과 같이 char type 변수를 생성할 수 있습니다.
let banana = 'A';
let banana:char = 'A';
let banana = '김';
let banana = '🐱';
2. Compound type#
Compound type(복합 타입)은 여러 Type의 값을 하나로 묶을 수 있습니다.
tuple 과 array 의 두 가지 type을 설명드리겠습니다.
2.1 tuple type#
다음 코드와 같이 괄호 ( )를 사용하여 여러 type의 값을 tuple로 묶을 수 있습니다.
tuple은 한번 선언되면 크기를 변경할 수 없습니다.
let apple: (i32, f32, char) = (10, 1.23, 'A');
let banana = (10, 1.23, 'A');다음 코드의 let (a, b, c) = banana; 같이 tuple을 해체 할 수 있습니다.
let banana = (10, 1.23, 'A');
let (a, b, c) = banana;
let sum = a + b;
println!("a = {a}");
println!("b = {b}");
println!("c = {c}");
println!("a + b = {sum}");다음은 실행 결과 입니다.
a = 10
b = 1.23
c = A
a + b = 11.23tuple은 다음 코드와 같이 .index를 사용하여 접근할 수 있습니다.banana.0은 10을 가리키고, banana.1은 1.23을 가리킵니다.
첫번째 원소의 index는 0 입니다.
let banana = (10, 1.23, 'A');
println!("index 0 = {0}", banana.0);
println!("index 1 = {0}", banana.1);
println!("index 2 = {0}", banana.2);다음은 실행 결과 입니다.
index 0 = 10
index 1 = 1.23
index 2 = A만일, 다음 코드의 banana.99와 같이 tuple의 index 범위를 벗어나는 경우 Runtime이 아닌 Compile 과정에서 오류를 발생 시킵니다.
이것은 SW의 Runtime 안정성을 향상 시킬 수 있습니다.
let banana = (10, 1.23, 'A');
println!("index 2 = {0}", banana.99);다음은 실행 결과 입니다.
error[E0609]: no field `99` on type `({integer}, {float}, char)`
--> code1.rs:5:38
|
5 | println!("index 2 = {0}", banana.99);
| ^^ unknown field
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0609`.2.2 array type#
Array는 같은 타입의 요소들로만 구성되며 고정된 길이를 갖습니다.
배열을 생성하는 몇 가지 방법을 알아 봅시다.
다음 코드는 int type의 1, 2, 3 세개의 원소를 가지는 Array을 만드는 예제 입니다.
let arr = [1, 2, 3];다음 코드와 같이 type과 size를 명시하여 Array를 생성할 수 있습니다.
let arr:[i32; 3] = [1, 2, 3];Array의 원소에 접근할 때는 다음 코드의 arr[0]과 같이 Index로 접근할 수 있습니다.
let arr = [1, 2, 3];
println!("{}", arr[0]);
println!("{}", arr[1]);만일 다음 코드의 arr[9]와 같이 Array 범위를 벗어나는 Index를 하드코딩 하는 경우 컴파일 과정에서 에러를 발생시킵니다.
이것은 런타임 오류를 사전에 방지하는데 도움을 줍니다.
let mut arr = [1, 2, 3];
arr[9] = 99;다음은 실행 결과 입니다.
error: this operation will panic at runtime
--> code1.rs:10:5
|
10 | arr[9] = 99;
| ^^^^^^ index out of bounds: the length is 3 but the index is 9
|
= note: `#[deny(unconditional_panic)]` on by default
error: aborting due to 1 previous error하지만, 다음 코드와 같이 Index가 하드코딩 되지 않고 변수일 경우 컴파일 과정에서 오류가 발생하지 않습니다.
Runtime에서 Panic을 발생시킵니다.
let mut arr = [1, 2, 3];
for i in 10..20 {
arr[i] = 99;
}다음은 실행 결과 입니다.
thread 'main' panicked at code1.rs:7:9:
index out of bounds: the len is 3 but the index is 10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace