0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クラウド開発環境PaizaCloudクラウドIDEでHello World(Rust編 その2 構造化と所有権を試す)

Posted at

はじめに

クラウド開発環境 PaizaCloud IDE(以下、PaizaCloud)を開発環境としたHello World シリーズを書いています。今回のRust編のその2です。

前回(Hello World Rust編 その1)では、println! の使い方やフォーマット指定を中心に、 Rustの基本的な出力の書き方を確認しました。 また、今回もChatGPTに教えてもらいながら私自身がRustを学びながら試していく「自分のためのHello World」です。 そのような感じで呼んでいただければうれしいです。

今回は、C言語でもおなじみの「構造化3要素」すなわち 順次・分岐・繰り返し をRustで試してみます。 ついでに、配列と所有権(Ownership)の基本にも触れてみます。

前回と同様ですが、C言語は知らないという場合はC言語に関する記述は無視して頂いてRustに関する内容だけ読んでいただければと思います。たまにPythonではともありますがそれも同じです。

🧩 構造化3要素(順次・分岐・繰り返し)

1. 順次処理

fn main() {
    println!("--- 順次処理 ---");

    let mut x = 10;
    x += 5;
    println!("x = {}", x);
}

xに10を代入して、順に5を足すという処理です。

出力:

--- 順次処理 ---
x = 15

PaizaCloudでの操作の例のスクリーンショットです。ここからはスクリーンショットは割愛します。
paiza1.png

プログラムの書き方としてはC言語とほぼ同じです。
Rustでは let mut をつけることで、変数 x が変更可能になります。
(mut を忘れると「イミュータブル(変更できない)」というエラーになります。)

2. 分岐(if文)

fn main() {
    let x = 15;

    if x > 10 {
        println!("x は 10 より大きい");
    } else if x == 10 {
        println!("x は 10 ちょうど");
    } else {
        println!("x は 10 未満");
    }
}

10を基準に判定、分岐しています。

出力:

x は 10 より大きい

Rustの if は式としても使えるのが特徴です。
たとえば次のように、条件分岐で値を代入できます👇

fn main() {
    let x = 8;
    let result = if x > 10 { "big" } else { "small" };
    println!("x は {}", result);
}

出力:

x は small

💡 if文が「式」になっているので、C言語のように ?: 三項演算子が不要になります。

3. 繰り返し(for文)

fn main() {
    println!("--- for文 ---");

    for i in 0..5 {
        println!("i = {}", i);
    }
}

出力:

--- for文 ---
i = 0
i = 1
i = 2
i = 3
i = 4

0..5 は「0以上5未満」という範囲を表します。
Pythonの range(0, 5) に近い感覚です。

🔹 for 文のほかにも、while や loop(無限ループ)もあります。
今回は for で確認しました。

🧩 配列とループ

fn main() {
    let nums = [10, 20, 30, 40];
    println!("--- 配列の中身 ---");
    for n in &nums {
        println!("{}", n);
    }
}

出力:

--- 配列の中身 ---
10
20
30
40

C言語の for (i=0; i<4; i++) printf("%d", nums[i]); にあたります。
Rustではインデックス不要で直接要素を回せるのが特徴です。

また、インデックスを使いたい場合は enumerate() を使います。

fn main() {
    let nums = [10, 20, 30, 40];
    println!("--- 配列の中身 ---");
    for (i, n) in nums.iter().enumerate() {
        println!("nums[{}] = {}", i, n);
    }
}

💡ここまでの印象

まあここまではこういう書き方なのかという感じでそれほど難しくは感じませんがいかがでしょうか。ここからRustらしい記述方法について試します。

🧠 所有権(Ownership)

Rustの特徴といえば「所有権」です。
この「所有権」を見てみます。

fn main() {
    let s1 = String::from("Hello");
    let s2 = s1; // 所有権が s1 → s2 に移動(ムーブ)

    println!("{}", s2);
    // println!("{}", s1); // ← ここはエラー!
}

出力:

Hello

s1 の内容が s2 に「ムーブ」したため、s1 はもう使えません。
C言語でいう「同じメモリアドレスを別のポインタで触る」ようなバグを、Rustはコンパイル時に防いでくれるということです。参考までに、println!("{}", s1);の行を有効にすると以下のようなコンパイルエラーが出ます。丁寧に説明しているようですが所有権の考え方を知らないと理解するのが難しいですかね。

  |
3 |     let s2 = s1; // 所有権が s1 → s2 に移動(ムーブ)
  |         ^^ help: consider prefixing with an underscore: `_s2`
  |
  = note: #[warn(unused_variables)] on by default

error[E0382]: borrow of moved value: `s1`
 --> rust1.rs:6:21
  |
2 |     let s1 = String::from("Hello");
  |         -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait
3 |     let s2 = s1; // 所有権が s1 → s2 に移動(ムーブ)
  |              -- value moved here
...
6 |      println!("{}", s1); // ← ここはエラー!
  |                     ^^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.

🔗 借用(Borrow)

次は借用です。
ムーブでは所有権が移ってしまいますが、
「一時的に中身を使いたいだけ」という場合は 借用(Borrow) を使います。

🟢 不変参照(&T)

中身を読むだけの参照です。複数同時に使えます。

fn main() {
    let s = String::from("Hello");
    let a = &s;
    let b = &s;
    println!("{}, {}", a, b); // ✅ 不変参照は複数OK
}

同じスコープ内で可変参照と不変参照を同時に持つとコンパイルエラーになります。(コンパイルエラーの内容は割愛します。気になった場合はぜひPaizaCloudで試してみて下さい。)

fn main() {
    let mut s = String::from("Hello");
    let a = &s;
    let b = &mut s; // ❌ コンパイルエラー
    println!("{}", a);
}

🔹 ここでのポイント

Rustでは読み専用参照は何個でもOK、書き込み参照は1個だけ。
このルールで「同時アクセスによるデータ破壊」をコンパイル時に防ぐことができます。

📘 所有権と借用のまとめ

概念 意味 同時に使える数 備考
所有権(Move) 値の持ち主を移動 1つだけ 代入で移動、元変数は無効
クローン(Clone) 実体をコピー 複数可 メモリコストがかかる
借用(Borrow) 所有権を移さず参照 & は複数OK、&mut は1つだけ 参照のスコープが重なるとエラー

今回のまとめ

  • 構造化3要素(順次・分岐・繰り返し)はRustでもそのまま使える
  • 配列をfor文で直接回せる
  • 所有権(Ownership)のおかげでメモリの扱いが安全
  • 「誰が値を持っているか」と「いつ使えるか」をコンパイル時に厳密に管理
  • 「どこで書き換わったかわからない」を防ぐ仕組み
  • コンパイラのエラーメッセージが親切(提案までしてくれる)
  • PaizaCloudでも簡単に実行可能

👴 さいごに感想など

Rustでは「実行してみないと分からない問題」をコンパイル時に発見・防止しようという設計が随所に見られました。

メモリ安全性や並行性の課題も、プログラムが動く前に“ルール違反”として教えてくれるので、実行時エラーや予測不能な挙動を未然に防ぐことができます。(但し、そのルールを理解しないとコンパイルエラーの意味が分からないかもしれないと思いました。)

これはC/C++との大きな違いであり、Rustの特徴そのものだと感じました。

いかかでしたでしょうか?引き続きRustについても書けたらと思います。
ありがとうございます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?