티스토리 뷰
반응형
변수 선언 let
let 은 immutable (수정할 수 없는) 변수입니다.
let x = 3;
x = 7; // 컴파일에러!
println!("x의 값은 {x} 입니다.");
let mut 은 mutable (수정할 수 있는) 변수 입니다.
let mut x = 3;
x = 7;
println!("x의 값은 {x} 입니다."); // 성공
상수 선언 const
상수선언 다른 언어처럼 const 로 선언하며, 반드시 타입을 명시해줘야 합니다.const는 컴파일 타임에 결정되는 수정할 수 없는 상수 변수이기 때문에 당연히 const mut 처럼 사용할 수 없습니다.
const PI:f32 = 3.141592;
fn main() {
println1("PI 상수값은 {PI}입니다.");
}
변수 가리기 shadowing
- 기존의 변수와 같은 이름으로 변수를 선언하면 가장 마지막 변수로 예전 변수가 가려집니다.
- 어디서든 스코프를 만들어서 변수를 다시 선언하여 사용할 수도 있습니다. 스코프의 범위가 끝난 후에는 기존 변수가 불러와집니다.
fn shadowing() {
let x = 3;
println!("x의 값은 {x}입니다");
let x = x + 1; // 기존의 x 변수가 덮어쓰기 된다.
println!("x의 값은 {x}입니다");
{
let x = x * 2;
println!("안쪽 범위에서 x의 값은 {x}입니다");
}
println!("x의 값은 {x}입니다");
}
Scalar 데이터 타입
- 정수
| 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 |
- 정수 리터럴 표현
| 10진수 | 19_384 | 3개씩 끊어서 인간이 잘 읽을 수 있게 표기할 수 있다 |
| 16진수 | 0xff | |
| 8진수 | 0o77 | |
| 2진수 | 0b1111_0010 | 4비트씩 끊어서 표기할 수 있는 표현법 |
| 바이트 u8 | b’A’ |
- 부동 소수점 floating-point
| 32 bit | f32 | |
| 64 bit | f64 | 속도차이가 크지 않기때문에 보통 이걸 쓴다. |
- 숫자 기본연산
let truncated = 3 / 2; // 1 이라고 몫만 정수로 나온다.
// 기본적인 4칙연산 방식은 다른 언어와 동일
// 아래와 같은 상황은 주의 필요!
let first: u8 = 3;
let second: u16 = 5;
let thired = first + second; // mismatched type Error
- boolean 타입
let t = true;
let t:boolean = false;
- char 타입
let c = 'A'; // 4bytes
let z: char = '가'; // 유니코드 값 하나와 대응되기 때문에 '가' 를 넣어도 된다.
let unicorn: char = '☆' // 유니코드 값과 대응되기 때문에 이모지도 삽입가능.
Compound 데이터 타입
- tuple 타입
let t: (f32, bool, f64) = (32, true, 1.41); // 3개의 다른 타입을 갖고 있는 튜플 t 생성
let (x, y, z) = t; // 구조분해를 이용해서 t 에 있는 원소를 하나씩 꺼내 사용가능.
let x = t.0; // 튜플의 값을 인덱스를 이용해서 접근 가능.
let y = t.1;
- 특별한 튜플 unit 타입
- () : 아무것도 없는 tuple 타입. 빈 값을 반환한다.
- array 타입
- 같은 타입만 담을 수 있다. 배열의 크기는 처음 생성했을 때 고정된다.
let x = [1, 2, 3, 4, 5];
let x: [i32; 5] = [1, 2, 3, 4, 5]; //i32 타입이 5개 들어가는 배열을 만든다.
let threes = [3; 100]; // 3이 100개 들어있는 배열을 만든다.
let last = threes[99];
println!("{last}"); // 3
String 타입과 문자열 리터럴
- 문자열 리터럴은 immutable 하다.
- 그래서 사용자의 입력을 받아야 하는 문자열은 mutable 한 String 타입으로 관리한다.
- 문자열 리터럴은 스택에 저장되지만, String 타입은 heap 메모리에 저장된다.
fn main() {
let hello = "헬로"; // 문자열 리터럴
let mut s:String = String::from("헬로"); // String 타입
s.push_str(", 월드!"); // 값을 붙일 수 있다.
println!("s={}", s);
}
String
String 타입 변수를 선언하는 다양한 방법
// 1번
let data = "initial";
let s = data.to_string();
// 2번
let s2 = String::from("initial");
// 3번
let s3 = "intial".to_string();
String 변수를 수정하는 방법
fn main() {
let mut s = String::from("initial");
s.**push_str(" data");** // &str append
s.**push('!');** // char append
println!("{s}"); // initial data!
}
fn main() {
let mut s = String::from("initial");
let s2 = String::from(" data");
s = s + **&s2** + " is always important!"; //&s2 말고 그냥 s2 를 하면 오류가 난다. &str 타입만 + 로 연결 가능.
println!("{s}"); // initial data is awlays important!
}
// 띄어쓰기를 고려하는게 귀찮다면 이런 방법도 있다.
fn main() {
let s1 = String::from("initial");
let s2 = String::from("data");
let s3 = "is always important!";
let s = **format!("{s1} {s2} {s3}");**
println!("{s}"); // initial data is awlays important!
}
Vector
러스트의 벡터는 아래와 같이 생성할 수 있다. (https://doc.rust-lang.org/std/vec/struct.Vec.html 참고)
let v:Vec<i32> = Vec::new();
let v = vec![1, 2, 3];
let mut vec = Vec::with_capacity(5); // 5의 캐퍼를 갖고 생성. 구조는 C++ 이라 동일
let mut vec = Vec::from(v.clone()); // 이런것도 가능!
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
// 다양한 iterating 방법들 모두 v에 1, 2, 3 이 들어있다고 가정한다.
while let Some(top) = v.pop() { //stack 처럼 활용가능.
println!("{top}");
}
// 기본 iterating 방법. 1\\n2\\n3\\n 을 출력한다.
for i in &v {
println!("{i}");
}
// iterating 하면서 수정하고 싶으면?
for i in &mut v { // 물론 v는 mut 로 생성되어 있어야 함.
*i += 50;
}
아래와 같은 경우는 에러가 난다.
fn main() {
let mut v = vec![1, 2, 3, 4, 5];
let first = &v[0];
v.push(6);
println!("The first element is: {first}");
}
push() 로 인해 first 의 값이 변경될 수 있다고 판단하여 println!() 에서 에러가 발생한다. println!() 을 push() 문 위로 이동시킨 후 실행하면 정상적으로 출력된다.
반응형