Rust 찍어먹기 1

Lapis0875·2023년 3월 2일
0

Rust

목록 보기
1/1
post-thumbnail

🤔 Rust? 그게 뭔데

Rust는 컴파일러가 매우 똑똑한 프로그래밍 언어에요.
지난 해 C언어를 다시 배워보면서 C의 포인터 등이 강력하긴 했지만 별로 마음에 들지 않았던 차에, Rust 얘기를 좀 들어보니 배워보고 싶어지더라고요.
이번에 개강이기도 하니, 이참에 뭐 하나 새로 배워보자! 하고 도전해봤습니다.
간단하게 기본 문법들을 짚어보며 배운 내용들을 조금씩 정리해볼게요.

변수 선언

Rust에서 변수 선언은 let 키워드를 사용해요. 변수의 타입은 변수명 뒤에 :타입 형태로 작성해요. 이렇게 선언된 변수들은 기본적으로 불변이에요.

let x: i32 = 1;
let y: f64 = 3.14;

변수의 값을 변경할 수 있는, 가변변수로 만들기 위해서는 mut 키워드를 함께 사용해야 해요.

let mut z: i32 = 42;
z = 32;

Rust는 정적 타입 언어이자 강타입 언어로, 모든 타입 검사가 컴파일 시점에 이루어진다고 해요. 동시에 타입 추론을 지원해서, 변수의 타입 선언은 생략될 수 있어요.

let x = 1;		// 정수 값은 기본적으로 i32로 타입 추론됩니다.
let y = 3.14;	// 실수 값은 기본적으로 f64로 타입 추론됩니다.

섀도잉

앞서, let만 사용해 선언한 변수는 불변이라고 했어요. 하지만 변수 자체를 다시 선언해서 값을 바꿀 수는 있어요. 이를 섀도잉이라고 해요.

let x = "42";

let x = 1;

println!("{}", x);	// 이후에 선언된 x의 값인 1이 출력돼요.

Rust의 타입들

모든 타입을 소개하진 못하고, 기본적인 타입들 몇가지를 소개할게요.

타입설명
i88비트 정수
i1616비트 정수
i3232비트 정수
i6464비트 정수
i128128비트 정수
isize아키텍처
u8부호 없는 8비트 정수
u16부호 없는 16비트 정수
u32부호 없는 32비트 정수
u64부호 없는 64비트 정수
u128부호 없는 128비트 정수
usize부호 없는 아키텍처
f3232비트 부동소수점 실수
f6464비트 부동소수점 실수
bool불리언(boolean)
String문자열
str문자열 슬라이스

💡 isize, usize는 컴퓨터 아키텍처가 32비트인지 64비트인지에 따라 크기가 달라지는 기본 포인터 크기에요.

🔎 String과 str이 뭐가 다른걸까요?

타입 캐스팅

Rust에서 타입 캐스팅을 할 때는 as 키워드를 사용해요.

let f = 3.14;
let i = f as i32;

println!("{} -> {}", f, i);		// 3.14 -> 3

상수 선언하기

상수를 선언하는 키워드가 따로 있어요. 몇몇은 익숙할 것 같은, const 키워드에요. Rust의 작명 규칙에 따르면, 상수는 SCREAMINGSNAKE_CASE (모두 대문자로 쓰고, 단어 구분은 언더바(``)로 하는 방식이에요.) 로 작성해요.

const PI: f64 = 3.14;

🔎 let으로 선언한 변수도 이미 불변인데, 굳이 const로 상수를 선언하는 이유는 뭘까요?

함수 선언하기

러스트에서 함수는 fn 키워드로 선언해요.

fn hello() {
	println!("Hello World!");
}

인자와 반환값을 가질 경우, 인자와 반환값 모두 타입을 선언해줘야 해요.

fn add(num1: i32, num2: i32) -> i32 {
	return num1 + num2;
}

Rust는 함수의 코드 마지막에서 return문을 생략할 수 있어요. 이 때, 세미콜론이 없다는 점에 주의하세요.


fn add(num1: i32, num2: i32) -> i32 {
	num1 + num2
}

함수 호출은 아래와 같이 해요.

fn main() {
	let res = add(1, 2);
	println!("1 + 2 = {}", res);
}

여러개의 값 반환하기

Rust의 함수에서 둘 이상의 값을 반환할 때는, 값을 튜플로 묶어 반환할 수 있어요.

fn swap(num1: i32, num2: i32) -> (i32, i32) {
	(num2, num1)
}

fn main() {
	let mut x = 1;
    let mut y = 2;
    println!("x = {}, y = {}", x, y);		// x = 1, y = 2
    (x, y) = swap(x, y);
    println!("x = {}, y = {}", x, y);		// x = 2, y = 1
}

리턴값이 없는 경우

앞서 함수의 반환값도 타입 표기를 해야 한다고 이야기했는데, 그럼 함수가 아무것도 반환하지 않을 때는 어떻게 해야할까요?
아래 greeting 함수는 별다른 값을 반환하지 않아요. 이 경우, 반환값의 타입 표기 자체를 생략할 수 있어요.

fn greeting() {
	println!("Hello World!");
}

또는, 반환값의 타입을 ()로 표기할 수 있어요.

fn farewell() -> () {
	println!("Good bye!");
}

이 때, 반환값이 없는 함수의 반환값을 println! 등으로 출력하려면 어떻게 해야 할까요? 말이 좀 이상하지만, 이렇게 반환값이 없는 함수의 반환값을 출력하려고 하면 오류가 발생해요.

println!("{}", farewell());		// error[E0277]: `()` doesn't implement `std::fmt::Display`

이럴 때는, 포맷 문자열을 아래처럼 사용해주면 돼요.

println!("{:?}", farewell());
profile
새내기 대학생 개발자에요 :D

0개의 댓글