본문 바로가기
Rust

Rust 설치부터 실행까지 (데이터 타입, 튜플, 어레이) - 5

by lms0806 2024. 12. 28.
728x90
반응형

오늘은 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는 부호가 없는 즉, 자연수들입니다.

 

그냥 intunsigned 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'

부동 소수점 타입

러스트에서 부동 소수점 숫자 타입으로는 f32f64로, 각각 32bit와 64bit의 크기를 가지고 있습니다.

 

기본 타입은 f64인데, 그 이유는 현대 CPU상 f64f32와 비슷한 속도를 내면서 더 정밀하기 때문입니다.

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타입으로는 다른 언어들처럼 truefalse 두 값을 가질 수 있습니다.

 

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의 에러 처리 및 패닉을 일으키지 않으면서 유효하지 않은 메모리 접근도 허용하지 않는 안전한 코드 작성 방법에 대해서는 추후에 다루도록 하겠습니다.

정리

  1. 러스트는 i8, u8, i16, u16, i32, u32, i64, u64, i128, u128로 정수형 타입이 존재하고, f32, f64로 부동 소수점 타입이 존재하고, bool로 boolean 타입이 존재합니다.
  2. 복합 타입으로는 여러 타입들을 사용할 수 있는 tuple이 있고, 스택 메모리에 저장되면서 고정된 길이와 동일한 타입으로 이루어진 array타입이 존재합니다.
728x90
반응형

댓글