Skip to content

타입과 변수

변수 정의

  • 변수를 정의할 때는 let 키워드를 사용한다.
  • 타입 추론을 지원하기에 타입 정의 부분을 생략해도 된다.
let thing1: i32 = 100;
let thing2 = 200 + thing1;
// mut은 mutable을 의미하는 것으로, 수정 가능한 변수인지를 표현한다.
let mut changing_thing = true;
changing_thing = false;
let (part1, part2) = ("first", "second");
struct Example {
a: bool,
b: u64,
}
let Example { a, b: _ } = Example {
a: true,
b: 10004,
};
assert!(a);
// 변수 이름을 shadowing 해서 정의할 수도 있다.
// shadowing을 하면 새로운 변수가 생기며, 이전 변수와 새 변수는 메모리의 서로 다른 위치에 존재한다.
let shadowing_example = true;
let shadowing_example = 123.4;
let shadowing_example = shadowing_example as u32;
let mut shadowing_example = format!("cool! {shadowing_example}");
shadowing_example += " something else!"; // not shadowing
println!("{shadowing_example}")
  • const로 선언하면 컴파일 할 때 그 값이 정해지며, 상수가 사용되는 모든 부분에서 인라인된다.
  • static 변수는 프로그램이 수행되는 동안 유지되며, 다른 변수로 이동(move)되지 않는다.

타입

이름타입비트리터럴 값
부호있는 정수i8, i16, i32, i64, i128 (isize는 포인터 크기)N 비트 (알파벳 뒤의 숫자와 동일)-10, 0, 1_000, 123_i64
부호없는 정수u8, u16, u32, u64, u128 (isize는 포인터 크기)N 비트0, 123, 10_u16
부동소수f32, f64N 비트3.14, -10.0e20, 2_f32
문자열&str포인터 크기"foo", "two\nlines"
유니코드 문자char32 비트'a', 'α', '∞'
불린bool8 비트true, false

복합 타입

이름타입리터럴 값
배열[T; N][20, 30, 40], [0; 3]
튜플(), (T,), (T1, T2), …(), ('x',), ('x', 1.2), …
  • 배열

    • 배열은 같은 타입 T의 값이 N개 있는 것이고 N은 컴파일 타임에 결정된 값이어야 한다.

    • 길이도 배열 타입의 일부이기에, [u8; 3][u8; 4]은 서로 다른 타입이다.

      ```rust
      fn main() {
      let mut a: [i8; 10] = [42; 10];
      a[5] = 0;
      println!("a: {:?}", a);
      }
      ```
    • 배열의 일부를 슬라이스 해서 가져올 수 있다.

    • 슬라이스는 큰 컬랙션의 일부(혹은 전체)를 보여주는 뷰(view)이며, 다른(슬라이스 된) 타입으로부터 데이터를 빌려온다. 다시말해 소유권을 갖지 않는다.

    • 메모리 안전을 위해 슬라이스가 선언, 사용될 때는 원본 배열과 슬라이스 배열을 수정할 수 없다. 슬라이스가 사용되지 않을 때, 즉 슬라이스를 만들기 전이나, 혹은 println이후에는 a[3]을 바꿀 수 있다.

      fn main() {
      let mut a: [i32; 6] = [10, 20, 30, 40, 50, 60];
      println!("a: {a:?}");
      // 인덱스 0부터 시작한다면 시작 인덱스는 생략 가능하다.
      let a1: &[i32] = &a[..a.len()] // = &a[0..a.len()]
      // 마지막 인덱스도 생략 가능하다.
      let a1: &[i32] = &a[2..] // = &a[2..a.len()]
      // 전체 배열에 대한 슬라이스는 &a[..]
      let s: &[i32] = &a[2..4];
      println!("s: {s:?}");
      }
  • 튜플

    • 튜플은 서로 다른 타입의 값들을 하나의 복합 타입으로 묶는다.

    • 튜플에 속한 값은 t.0, t.1과 같이 인덱스로 접근할 수 있다.

    • 비어있는 튜플()은 단위 타입(unit type)이라고 하고, 함수나 식에서 반환 값이 없음을 나타낼 때 사용한다. (다른 언어의 void 개념과 비슷하다.)

      ```rust
      fn main() {
      let t: (i8, bool) = (7, true);
      println!("1st index: {}", t.0);
      println!("2nd index: {}", t.1);
      }
      ```

포인터

&를 통해서 포인터를 선언하고, *를 통해 역참조할 수 있다.

let mut ref_x: &i32let ref_x: &mut i32는 다른 의미이다. 첫번째 값은 다른 값에 바인딩 될 수 있는 가변 참조이고, 두번째 값은 가변 값에 대한 참조이다.

fn main() {
let mut x: i32 = 10;
let ref_x: &mut i32 = &mut x;
*ref_x = 20;
println!("x: {x}");
}

enum

  • 러스트는 열거형 variant를 구분하기 위해 내부적으로 식별자(discriminant) 필드를 사용한다.
// 일반 enum
enum CoinFlip {
Heads,
Tails,
}
// 데이터를 포함하는 enum (Variant Payloads)
enum WebEvent {
PageLoad, // Variant without payload
KeyPress(char), // Tuple struct variant
Click { x: i64, y: i64 }, // Full struct variant
}
#[rustfmt::skip]
fn inspect(event: WebEvent) {
match event {
WebEvent::PageLoad => println!("page loaded"),
WebEvent::KeyPress(c) => println!("pressed '{c}'"),
WebEvent::Click { x, y } => println!("clicked at x={x}, y={y}"),
}
}
fn main() {
let load = WebEvent::PageLoad;
let press = WebEvent::KeyPress('x');
let click = WebEvent::Click { x: 20, y: 80 };
inspect(load);
inspect(press);
inspect(click);
}

참고