오늘은 Rust의 데이터타입에 대해 알아보고자 합니다.
타 언어
JAVA의 경우 데이터 타입으로 int, long, double이 존재합니다.
C++의 경우 데이터 탕입으로 int, long long, long double 등 다양한 타입이 존재합니다.
정적 타입
Rust는 정적 타입의 언어로, 모든 변수의 타입이 컴파일 시점에 정해져 있어야 합니다.
다음과 같이 "42"라는 문자열을 정수형으로 변환하고자 할 때, u32라는 타입으로 지정해줍니다.
let guess: u32 = "42".parse().expect("Not a number!");
만약 u32 타입을 지정하지 않은 경우 다음과 같이 error가 발생합니다.
help: consider giving `guess` an explicit type
스칼라 타입
Rust는 정수, 부동 소수점 숫자, bool, 문자 이렇게 4개의 스칼라 타입을 가지고 있습니다.
정수형
정수형은 int, long과 같이 소수점이 없는 숫자입니다.
그 중, unsigned는 부호가 없는 즉, 자연수들입니다.
그냥 int와 unsigned int와 다른 점은 int는 -2,147,483,648 ~ +2,147,483,647, unsigned int는 0 ~ 4,294,967,295로 사용하는 범위가 다릅니다.
- rust의 정수형 타입들
길이 부호 있음(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
rust에서 표현하는 i8은 8비트의 값을 사용하는 것으로 -128 ~ 127까지의 값을 사용할 수 있습니다. 그리고, u8은 0 ~ 255까지의 값을 사용할 수 있습니다.
- rust의 정수형 리터럴
숫자 리터럴 예 Decimal 98_222 Hex 0xff Octal 0o77 Binary 0b1111_0000 Byte(u8 only) b'A'
부동 소수점 타입
러스트에서 부동 소수점 숫자 타입으로는 f32와 f64로, 각각 32bit와 64bit의 크기를 가지고 있습니다.
기본 타입은 f64인데, 그 이유는 현대 CPU상 f64가 f32와 비슷한 속도를 내면서 더 정밀하기 때문입니다.
fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
수치 연산
rust는 모든 숫자 타입에 대해서 기본 수학 연산 기능을 제공합니다.
fn main() {
// 덧셈
let sum = 5 + 10;
// 뺄셈
let difference = 95.5 - 4.3;
// 곱셈
let product = 4 * 30;
// 나눗셈
let quotient = 56.7 / 32.2;
let truncated = -5 / 3; // 결괏값은 -1입니다
// 나머지 연산
let remainder = 43 % 5;
}
bool 타입
rust의 bool타입으로는 다른 언어들처럼 true와 false 두 값을 가질 수 있습니다.
rust에서는 bool로 명시됩니다.
fn main() {
let t = true;
let f: bool = false; // 명시적인 타입 어노테이션
}
문자 타입
rust의 char는 기본적인 알파벳 타입입니다.
fn main() {
let c = 'z';
let z: char = 'ℤ'; // 명시적인 타입 어노테이션
}
복합 타입
복합 타입은 튜플(tuple)과 배열(array)로 두 가지 기본 복합 타입이 있습니다.
튜플 타입
튜플은 다양한 타입의 값들을 묶어 하나의 복합 타입으로 만드는 방법입니다.
fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}
튜플에서 개별 값을 가져올려면 다음과 같이 매칭하여 튜플값을 얻어올 수 있습니다.
fn main() {
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!("The value of y is: {y}");
}
tup에 500, 6.4, 1이라는 값을 넣은 후, x, y, z에 각각 값을 주입시킵니다. 이것들 구조 해체(destructuring)라고 부르는 이유는 튜플을 3부분으로 나누기 때문입니다.
마침표(.)을 사용하여 특정 부분의 값만 가져올 수도 있습니다.
fn main() {
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
let one = x.2;
}
() 빈 값으로 선언된 즉, 아무 값도 없는 튜플은 유닛(unit)이라는 특별한 이름을 갖습니다.
배열 타입
배열은 튜플과 달리 모든 요소의 타입이 동일해야 합니다. 또한, rust의 배열은 고정된 길이를 갖습니다.
fn main() {
let a = [1, 2, 3, 4, 5];
}
힙 메모리 보다는 스택 메모리에 데이터를 할당하고 싶을 때나 항상 고정된 개수의 요소로 이루어진 경우면 배열이 유용합니다.
만약 고정된 길이가 아닌, 길이를 늘리거나 줄일 경우에는 벡터(vector)를 사용하시면 됩니다. 이는 추후에 다뤄보도록 하겠습니다.
다음과 같이 배열에 타입과 요소의 개수를 적는 식으로도 배열을 선언할 수 있습니다.
fn main() {
let a: [i32; 5] = [1, 2, 3, 4, 5];
}
또한, 배열에 똑같은 값을 채우고 싶은 경우에는 다음과 같이 작성하시면 됩니다.
fn main() {
let a = [3; 5];
}
배열 요소 접근하기
rust에서 배열의 값 접근 방법으로는 다른 언어들과 비슷하게 다음과 같이 작성하시면 됩니다.
fn main() {
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];
}
유효하지 않은 배열 요소 접근
fn main() {
let a = [1];
let first = a[1];
}
인덱스가 배열 길이보다 크거나 같을 경우 러스트는 패닉(panic)을 일으킵니다.
thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 1', src/main.rs:4:4
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
rust의 에러 처리 및 패닉을 일으키지 않으면서 유효하지 않은 메모리 접근도 허용하지 않는 안전한 코드 작성 방법에 대해서는 추후에 다루도록 하겠습니다.
정리
- 러스트는 i8, u8, i16, u16, i32, u32, i64, u64, i128, u128로 정수형 타입이 존재하고, f32, f64로 부동 소수점 타입이 존재하고, bool로 boolean 타입이 존재합니다.
- 복합 타입으로는 여러 타입들을 사용할 수 있는 tuple이 있고, 스택 메모리에 저장되면서 고정된 길이와 동일한 타입으로 이루어진 array타입이 존재합니다.
'Rust' 카테고리의 다른 글
Rust 설치부터 실행까지 (주석, 조건 반복문) - 7 (0) | 2024.12.30 |
---|---|
Rust 설치부터 실행까지 (함수, 구문, 표현식) - 6 (0) | 2024.12.28 |
Rust 설치부터 실행까지 (섀도어) - 4 (0) | 2024.12.26 |
Rust 설치부터 실행까지 (형변환 및 에러 처리) - 3 (0) | 2024.12.20 |
Rust 설치부터 실행까지 (feat. dependencies) - 2 (0) | 2024.12.19 |
댓글