やっつけな日常(40) Rustに入ればRustに従え、unsafeだらけの可変static

Joseph Halfmoon

「C言語」頭の老人には毎度恐れいるばかりのRustであります。今回はstaticとな。C言語であればスコープにかかわりなく静的に「持続する」変数を使うことができるアレです。Rustにもstaticあり。似たものに見えて、そのように使えないこともないのですが、制限キビシーです。unsafeの嵐。やってはいけないってこと?

※「やっつけな日常」投稿順 Index はこちら

いつもお世話になっております「Rust By Example 日本語版」様の以下のページを読んでおりましたら「Rustには2種類の定数あり」と。

定数

その心は

    • const
    • static

の2つだそうです。const が定数であることに異を唱える気は毛頭ありませぬが、staticも「定数」なの? staticっていうのはライフタイム的な、変数の存続期間じゃないの?と。。。 1か所引用させていただきましょう。

The static lifetime is inferred and does not have to be specified. Accessing or modifying a mutable static variable is unsafe.

mutableなstatic variableの変更はunsafeだと。ひっくり返せばC言語同様に変更できるってことじゃないの? でも、やってみて思い知ったです。

今回実験のソース

今回は、Cでいう大域変数のstatic と ローカル変数のstaticの両方を作ってみました。まず「変数」と思って小文字で「変数名」を書くだけで、RUSTコンパイラからお叱りをうけます。大文字で始めろと。たしかに名前でみても完全「定数扱い」されてますなあ。

Cではフツーな感じで書いてしまうとコンパイルエラー出まくります。staticな定数に mut なんて宣言すんじゃねえよ、という圧力をひしひしと感じます。めげずに、エラー箇所を必殺の unsafeで囲んでいきました。

unsafe { }

出来上がった実験コードが以下に

static mut GS000: i32 = 100;

fn func000() -> i32 {
    unsafe {
        GS000 += 1;
        return GS000;
    }
}

fn func001() -> i32 {
    static mut SS1: i32 = 0;
    unsafe { 
        SS1 += 1;
        return SS1;
    }
}

fn main() {
    unsafe { println!("GS000: {}", GS000); }
    println!("func000: {}", func000());
    unsafe { println!("GS000: {}", GS000); }
    println!("func000: {}", func000());
    println!("func001: {}", func001());
    println!("func001: {}", func001());
    println!("func001: {}", func001());
}

短いコードですが、unsafeだらけで汚いです。とほほ。

実行結果

走らせた結果が以下に。

mutStaticResult

一応、C言語的な動作をさせることはできましたが、汚い、圧倒的に汚い。もっと他に方法があるはず。またそのうち。

やっつけな日常(39) RustにいればRustに従え、Rust再インストール後動作確認 へ戻る

やっつけな日常(41) RustにいればRustに従え、配列の大きさ、usizeって何よ? へ進む