Rust Language Study Ch1: Variable and Data-type

이 포스트는 Rust를 공부하고 기록한 포스트입니다. 개인적으로 Rust에 관심이 있었기도 했지만, Go에 관심이 있고 같이 배우자는 팀원분의 제안에 오기가 생겨서 공부를 시작하였습니다. 현재 시스템하고 Pwnable에 관심…이 있다고 말할 실력을 갖는 것을 목표로 공부하고 있습니다.

1. 변수와 가변성

기본적으로 불변성 : 값이 이름에 Bound 되면 해당 값을 변경할 수 없음.

fn main(){
    let x = 5;
    println!("The value of x is: {}", x);
}

mut을 추가하므로서 가변성 변수를 선언할 수 있음.

fn main(){
    let mut x = 5;
    println!("The value of x is: {}", x);
}

대규모 데이터 구조체를 다루는 경우 가변한 인스턴스를 사용하는 것이 새로 인스턴스를 할당하고 반환하는 것보다 빠를 수 있다.

2. 상수

불변성 변수처럼 변경이 허용되지 않음.

불변성 변수와의 차이

  1. mut을 사용하는 것이 허용되지 않음.
  2. 값의 유형을 선언해야함.
  3. 어떤 영역에도 선언될 수 있음. => 많은 부분에서 사용될 필요가 있는 값을 다루는데 이용.
  4. 표현식만 설정될 수 있다.
const ARR_MAX: u32 = 100_000;

자신이 선언되어 있는 영역 내에서 프로그램이 실행되는 시간 동안 항상 유효하다.

3. Shadowing

이전에 선언한 변수와 같은 이름의 새 변수를 선언할 수 있고, 새 변수는 이전의 변수를 shadows하게 됩니다. let 키워드를 사용해서 다음처럼 반복하여 같은 변수 명으로 변수를 shadow 할 수 있음.

fn main(){
    let x = 5;
    let x = x + 1;
    let x = x * 2;
    println!("The value of x is: {}", x);
}

mut 과의 차이점

  1. let 키워드를 사용하지 않고 변수에 새로 값을 대입하려고 하면 컴파일-시에 에러가 출력됨. => 몇 번 값을 변경할 수는 있지만 그 이후에 변수는 불변성을 가짐
  2. let키워드를 사용하여 새 변수를 선언하고, 값의 유형을 변경할 수 있으면서도 같은 이름 사용 가능.

4. 데이터 타입

러스트의 데이터 타입

  • 타입은 크게 스칼라와 컴바운드 둘로 나눌 수 있음
  • Rust느 타입이 고정된 언어
  • 모든 변수의 타입이 컴파일 시에 반드시 정해져 있어야함

5. 스칼라 타입들

스칼라 타입 종류

  • 정수형
  • 부동소수점 숫자
  • Boolean
  • 문자

정수형 | Length | Signed | Unsigned | | —— | —— | ——– | | 8-bit | i8 | u8 | | 16-bit | i16 | u16 | | 32-bit | i32 | u32 | | 64-bit | i64 | u64 | | arch | isize | usize | 각 부호변수는 -(2^(n-1))~2^(n-1)-1까지의 값을 포괄합니다. isize와 usize타입은 당신의 프로그램이 동작하는 환경에 따라 결정됩니다. (32면 32bit, 64면 64bit)

정수의 리터럴 | Number literals | Example | | Decimal | 10_000 | | Hex | 0xff | | Octal | 0o77 | | Binary | 0b1101 | | Byte(u8 only) | b’A’ |

일반적인 상황에서는 i32가 가장 많이 사용됨. isize나 usize는 콜렉션 정렬을 색인할 때 사용됨

부동 소수점 타입 f32, f64를 가짐. 기본적으로 f64를 사용함. 이유: 속도가 비슷하지만 더 정밀하게 표현이 가능하기 때문 IEEE-754 표준에 따라 표현됨.

Boolean 타입 true와 false를 가지고 bool로 표기.

문자 타입 char 가장 근본적인 알파벳 타입 작은 따옴표로 표기함. Unicode Scalar를 표현하는 값이고 ASCII보다 많은 표현이 가능하다.

복합 타입들

다른 타입의 다양한 값들을 하나의 타입으로 묶을 수 있음 Rust는 기본적으로 튜플과 배열 두 개의 기본 타입들을 가지고 있음.

튜플 괄호안에 콤마로 구분되는 값 각 값의 타입이 동일할 필요없이 서로 달라도 무관.

fu main(){
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}

튜플은 단일 요소를 위한 복합계로 고려되었기에 변수 tup에는 튜플 전체가 bind됨. 값을 빼내오기 위해선 패턴 매칭을 사용하여 튜플의 값을 구조해체 시키면 됨

fn main() {
    let tup = (500, 6.4, 1);
    let (x, y, z) = tup;
    println!("{}", y);
}

마침표 뒤에 우리가 접근하길 원하는 값의 색인을 넣는 것을 통해 직접 접근이 가능합니다.

fn main() {
    let tup = (500, 6.4, 1);
    println!("{}", tup.1);
}

배열 튜플과 달리 모든 요소는 모두 같은 타입이여야함. 고정된 길이를 가짐 데이터를 heap보다 stack에 할당하는 것을 원하거나 항상 고정된 숫자의 요소를 갖는다고 확신하고 싶을 때 이용

배열이나 벡터(가변길이 유사 집합체) 중에 뭘 선택해야 할지 확실하지 않은 상황의 경우 벡터를 권함.

배열은 stack에 단일 메모리 뭉치로 할당됨. 색인을 통해 배열의 요소에 접근 가능.

fn main() {
    let arr = [1,2,3,4,5];
    
    println!("{}", arr[1]);
}

유효하지 않은 배열 요소에 대한 접근 ‘index out of bounds’ 라는 실행중 에러 (Runtime Error)가 발생했음 Panic : Rust에서 프로그램이 오류와 함께 종료 될 때 Rust는 잘못된 메모리 접근을 허용하는 대신 즉식 종료하여 사용자를 오류로부터 보호함.