Easy Rust Korean 011 ~ 020

Natreeum's Blog·2025년 11월 9일

Easy Rust Korean Study

목록 보기
2/5

011

mutability & shadowing

mutability : 변경가능여부

기본적으로 immutable (변수 선언 시 기본적으로 변경 불가능)

fn main(){
	let my_number = 10;
    my_number = 9;
}

>>> ERROR

my_number 는 immutable 이기 때문에 에러 발생
이 경우 mut 키워드를 사용해서 변경가능할 수 있게 해줘야함

fn main(){
	let mut my_number = 10;
    my_number = 9;
}

mut 키워드를 사용하고나서 변경되지 않았다면, 컴파일러가 이를 알려주고, mut 키워드 삭제 가능

shadowing : 같은 이름을 다시 쓰는 것

fn main(){
	let my_variable = 10;
   	let my_variable = "My Variable";
}

// -> my_variable 은 마지막에 작성된 "My Variable"만 값으로 생각함.

왜 사용?
코딩을 하면서 필요한 값은 최종 결과인데, 이를 위한 여러 변수들이 불필요하게 선언될 필요 없음

fn double(input: i32) -> i32 {
	input * 2
}

fn triple(input: i32) -> i32 {
	input * 3
}

fn main(){
	let x_origin = 9;
   	let x_double = double(x_origin);
    let x_final = triple(x_double);
    
    println!("{}", x_final);
}

// -> 결과적으로 필요한 값은 xFinal 인데, xOrigin, xDouble 같은 변수가 선언됨

//-----------Shadowing 으로 다음과같이 사용할 수 있음-----------
fn main(){
	let x = 9;
   	let x = double(x);
    let x = triple(x);
    
    println!("{}", x);
}

CodeBlock 을 이용해서 Shadowing을 다양하게 활용할 수 있음

fn main(){
	let my_var = 9;
    {
    	let my_var = "Some String";
        println!("{}", my_var); // Some String 출력
    }
    println!("{}", my_var); // 9 출력
}

012

Stack / heap / pointers

Stack Memory

먼저 들어온 Task가 다음에 들어온 Task가 종료될때까지 기다리는 메모리 구조.
Task가 종료되면 할당받은 Memory 는 반환

Heap Memory

창고같은 곳에서 "어디로 가면 어떤 물건이 있어요" 같이 동작하는 메모리 구조. 비교적 속도가 느리지만 많은 용량을 저장할 수 있음.

Pointers

아래와 같이 어떤 내용이 어디에 있는지 알려주는 역할

Chapter
Chapter 1: My life, Page : 1 
Chapter 2: My life, Page : 15
Chapter 3: My life, Page : 23 

Rust에서는 Pointer를 Reference 라고 부름.
reference 를 사용할 때에는 "&" 기호를 사용함.

fn main(){
	let my_number = 15; // 값. i32
    let single_reference = &my_number; // my_number 에 대한 싱글 레퍼런스. &i32
    let double_reference = &single_reference; // my_number 에 대한 레퍼런스에 대한 레퍼런스. &&i32
    
    let five_references = &&&&&my_number; // 이것도 사용 가능. 
}

싱글레퍼런스, 더블레퍼런스, 모두 다른 타입이기 때문에 상호 비교가 불가능!!

013

Fancy Printing : print!() 사용

아래 두 줄의 문장은 같은 동작을 함

println!(message);
print!("{}\n",message);

예를들면

fn main(){
	//#1
	println!("This");
    println!("is");
    println!("a");
    println!("message");
    
    //#2
    print!("This\n");
    print!("is\n");
    print!("a\n");
    print!("message\n");
    
    //#3
    print!("This\nis\na\nmessage\n");
}

위의 1, 2, 3번 코두 동일한 동작을 함

Output : 

This
is
a
message

\n 이라는 기호를 출력하고 싶다면? -> \\n 사용

fn main(){
	print!("This \\n is a message"); // Output : This \n is a message
}

그런데 \를 너무 많이 써야하는 상황이라면?
예를들어 다음 디렉토리를 표시하려면
c:\drive_a\new_drive\path_name

코드는 다음과 같이 안예뻐질 것

fn main(){
	print!("c:\\drive_a\\new_drive\\path_name");
}

이럴때 사용하는것이 "Raw Text"
다음과 같이 사용할 수 있다.

fn main(){
	print!(r#"c:\drive_a\new_drive\path_name"#);
}

줄바꿈을 다음과같이 사용할 수도 있는데

fn main(){
	println!("Let me tell you 
    some story
    about
    rust");
}

출력이 다음과 같다.

Let met tell you
	some story
    about
    rust

앞에 인덴트가 있기 때문에 그런것! 주의하여 사용할 것

전에 Debug Print 에 대해 잠시 다뤘는데

println!("{:?}", var_name);

으로 사용했다.

왜 물음표로 사용하냐면 어떤 타입이든 출력을 하기 때문.

특정 data type을 출력하기 위해선 다음과 같은 format을 사용한다

fn main(){
	let my_number = 9000;
	println!("{:p}", &my_number); // reference(pointer) 출력
    println!("{:X}", my_number); // Hex값 출력
    println!("{:b}", my_number); // Bytes값 출력

	println!("{:p}", my_number); // 는 오류 : p는 포인터 data type을 출력한다고 하는데, my_number 는 값이기 때문에
}

이 포맷을 조금 더 다양하게 활용이 가능하다.

fn main() {
    let title = "TODAY'S NEWS";
    println!("{:-^30}", title); // no variable name, pad with -, put in centre, 30 characters long
    let bar = "|";
    println!("{: <15}{: >15}", bar, bar); // no variable name, pad with space, 15 characters each, one to the left, one to the right
    let a = "SEOUL";
    let b = "TOKYO";
    println!("{city1:-<15}{city2:->15}", city1 = a, city2 = b); // variable names city1 and city2, pad with -, one to the left, one to the right
}

Output:

---------TODAY'S NEWS---------
|                            |
SEOUL--------------------TOKYO

더 많은 내용은 아래 링크 참고
https://doc.rust-lang.org/stable/std/fmt/

014

Strings

String / &str 을 주로 사용

fn main(){
	let my_name = "David"; // &str
    let other_name = String::from("David2");
    
    /*
    let my_other_name = "David3"; // &str
    my_other_name.push("!"); // 여기서 에러 발생!  &str 에는 .push 가 없기 때문
    */
    
    
    // 다음과 같이 하면 오류 발생 안함
    let my_other_name = "David3".to_string(); // String
    my_other_name.push("!");
    
    
    println!("{}", my_other_name);
}

String type 은 Sized type
str = dynamic type -> 길이를 컴파일러가 알 수 없음 => &str을 사용

015

&str 보다 String 이 사용하기 더 쉬운 이유!

method 사용이 용이함

.push : 한 글자 추가
.push_str : &str 추가
.capacity : 바이트 크기
.pop :
with_capacity : 바이트 크기 명시하여 String 선언

let mut my_name = "David".to_string();
my_name.push('!');
println!("My name is {}", my_name);
let mut my_name = String::with_capacity(26);
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
my_name.push_str("David!");
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
my_name.push_str("And I live in Seoul");
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());
my_name.push('a');
println!("Length is {} and capacity is {}", my_name.len(), my_name.capacity());

/* Output : 
Length is 0 and capacity is 26
Length is 6 and capacity is 26
Length is 25 and capacity is 26
Length is 26 and capacity is 26
*/

016

const / static

fn main(){
	let x = 8; // 'let' binding 이라고 함
}

const는 Global 변수를 선언함

const NUMBER: i32 = 20; // const 선언 변수명은 대문자로(소문자로 쓰면 warning), 타입 지정은 필수!

fn main(){
	let x = 8; // 'let' binding 이라고 함
}

static도 const와 비슷

const NUMBER: i32 = 20; // const 선언 변수명은 대문자로(소문자로 쓰면 warning), 타입 지정은 필수!
static LOW_SCORE: i32 = 0;

/*
static 은 mut 를 통해 unsafe 를 사용할 수는 있으나 거~~의 안씀!!

static mut LOW_SCORE: i32 = 0;
*/

fn main(){
	let x = 8; // 'let' binding 이라고 함
}

017

OWNERSHIP

fn main(){
	let country = String::from("대한민국");
    let ref_one = &country;
    let ref_two = &country;
    
    println!("Country is: {}", ref_one);
}
fn return_it() -> &String {
	let country = String::from("대한민국");
    &country // ref 반환
}

fn main(){
	let my_country = return_it(); // >> 오류!!
}

018

mutable references

& -> immutable reference / shared reference
&mut -> mutable reference / unique reference

fn main(){
	let mut my_number = 9;
    let num_ref = &mut my_number;
    
    /* 이렇게 코딩하면 오류남!! 
    num_ref = 10;
    */
    
    *num_ref = 10; // &의 반대개념 *
    
    // && 이면 ** 사용!
    /*
    	let num_ref = &mut &mut my_number;
        **num_ref = 10;
    */
}

019

references and shadowing

// 오류 반환됨!!
fn main(){
	let mut number = 10;
    let number_ref = &number;
    let number_change = &met number;
    *number_change += 10;
}
// 정상 작동됨
fn main(){
	let mut number = 10;
    let number_change = &met number;
    *number_change += 10;
    let number_ref = &number;
}

shadowing!

// 정상 작동됨
fn main(){
	let country = "대한민국";
    let country_ref = & country;
    let country = 8; // shadowing
    
    println!("{}, {}", country_ref, country); 
    // -> "대한민국" 이 없어지지 않았음을 확인할 수 있음!"
}

020

OWNERSHIP

fn print_country(country_name: String){
	println!("My country is {}", country_name);
}

fn main(){
	let country = "대한민국".to_string();
    print_country(country); // 여기서 country 의 소유권이 print_country 함수로 넘어감
    print_country(country); // 여기서 에러 발생!!
}
fn print_country(country_name: &String){
	println!("My country is {}", country_name);
}

fn main(){
	let country = "대한민국".to_string();
    print_country(&country); // 여기서 country 의 소유권은 넘어가지 않음!
    print_country(&country); // 에러 발생 X!
}
profile
BlockChain DEV

0개의 댓글