嵌入式工程师不熟悉的 Rust 符号

介绍

大家好,我是@yagisawa,一位传统的嵌入式工程师。

在学习 Rust 时,我有时会遇到在 C 中看不到的语言规范(主要是如何使用符号),因此我以类似备忘单的方式对其进行了总结。

随着我们了解更多,我们将继续更新。

"XXX 在锈等等我使用它”,但请注意,除了我在本文中介绍的方法之外,可能还有其他方法可以使用它,只是因为我没有足够的研究。

请注意,可能有我不知道的 C 用法。由于工作关系,我主要处理C89的规格。此外,由于本文的主要关注点是 Rust,C 信息的丰富性并不重要。

Rust 和 C 符号列表基于以下文章。

象征

!

在 C 中,它用于 論理否定非等価比較 等。

C。

// 論理否定
flg = !flg;

// 非等価演算
if ( flg != false ) { ... }

在 Rust 中,它用于 マクロ展開論理否定非等価比較

宏扩展

Rust 宏非常困难,所以让我们举一个 C 用户可能熟悉的例子。

macro_rules! abs {
    ($e: expr) => (if $e < 0 {-$e} else {$e})
}

fn main() {
    let ret = abs!(-2);
    println!("{}", ret);
}

我制作了一个熟悉的 (?) 宏,名为 abs。写abs! 来展开宏。

您可能已经注意到,Rust 是一个标准的输出处理宏。

如果您想了解更多关于宏的信息,请参阅下面的文章(或者更确切地说,我也会研究这个……)。

:

在 C 中,它用于 三項演算子ラベル 等。

C。

// 三項演算子
max = (val1 > val2) ? val1 : val2;

// ラベル
switch ( operator ) {
    case ADD: result = val1 + val2; break;
    case SUB: result = val1 - val2; break;
    case MUL: result = val1 * val2; break;
    case DIV: result = val1 / val2; break;
}

Rust 使用ラベル型制約構造体フィールド初期化子 等。

另外,Rust 的ラベル 仅限于ループラベル,你不能使用goto 在C 中随意跳转。细节是循环标签将进行描述。

顺便说一句,Rust 没有三元运算符。

类型约束

声明变量时使用了一个易于理解的示例。

fn main() {
    let x: u32 = 1024;
    println!("{}", x);
}

顺便说一句,Rust 有类型推断,所以

fn print_type_of<T>(_: T) {
    println!("{}", std::any::type_name::<T>())
}

fn main() {
    let x = 1024;
    print_type_of(x);
}

您可以声明一个变量而无需编写类似的类型(在我的执行环境中它是i32

顺便说一句,Rust 很聪明,

fn main() {
    let x: u8 = 1024;
    println!("{}", x);
}

如果你这样做

error: literal out of range for `u8`
 --> Main.rs:2:17
  |
2 |     let x: u8 = 1024;
  |                 ^^^^
  |
  = note: `#[deny(overflowing_literals)]` on by default
  = note: the literal `1024` does not fit into the type `u8` whose range is `0..=255`

error: aborting due to previous error

将导致错误。

结构字段初始化器

struct Point {
    x: i32,
    y: i32
}

fn main() {
    let origin = Point {x: 0, y: 0};
    println!("x = {}, y = {}", origin.x, origin.y);
}

当初始化一个名为originPoint 类型变量时,这样写。

;

在 C 语言中,我认为它只在句子中的 終端子 周围使用,但在 Rust 中,它在 終端子固定長配列記法 的一部分中使用。

固定长度数组表示法

fn main() {
    let a1: [i32; 5] = [1, 2, 3, 4, 5];
    println!("{:?}", a1);
    
    let a2 = [100; 5];
    println!("{:?}", a2);
}

在声明和初始化固定长度数组时这样写。

a1类型约束指定数组类型和大小。

a2 将所有元素初始化为 100。您没有指定a2 的类型,但类型和大小是从右值推断出来的。

'

在 C 中,我认为它只在文字 周围使用。

C。

char c = 'a';

Rust 使用文字ループラベル名前付きのライフタイム 等。

循环标签

在 Rust 中,你可以编写诸如 forwhileloop 之类的循环,但在其中

fn main() {
    let mut tbl = [[0; 3]; 3];
    tbl[1][2] = 10;

    'escape_label: for ary in tbl {
        for val in ary {
            println!("search!");
            if val != 0 { break 'escape_label; }
        }
    }
    
    println!("{:?}", tbl);
}

可以标记为通过使用break 指定标签,您可以一次退出多个循环。方便的。

寿命

我认为这是一个C用户不太了解的概念,所以让我们从一个C示例开始。

C。

#include <stdio.h>

int *max( int *val1, int *val2 ) {
    return (*val1 > *val2) ? val1 : val2;
}

int main( void ) {
    int x = 1;
    int *result;
    
    {
        int y = 10;
        result = max(&x, &y);
    }
    
    printf("%d\n", *result);
}

C 可以正常编译和运行这个程序。

输出结果正好是正确的,但是在max内(因为y的值更大),返回了y的指针并赋值给result,所以当printfresult时应该是out了的范围。尝试printf("%d %d\n", *result, y); 将导致错误。

如果你在 Rust 中做类似的事情,

fn max( val1: &i32, val2: &i32 ) -> &i32 {
    return if *val1 > *val2 { val1 } else { val2 };
}

fn main() {
    let x = 1;
    let result;
    
    {
        let y = 10;
        result = max(&x, &y);
    }

    println!("{}", result);
}
error[E0106]: missing lifetime specifier
 --> Main.rs:1:37
  |
1 | fn max( val1: &i32, val2: &i32 ) -> &i32 {
  |               ----        ----      ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `val1` or `val2`
help: consider introducing a named lifetime parameter
  |
1 | fn max<'a>( val1: &'a i32, val2: &'a i32 ) -> &'a i32 {
  |       ++++         ++             ++           ++

error: aborting due to previous error

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

出现“缺少生命周期说明符”的错误。

如果我像示例中一样添加生命周期参数

fn max<'a>( val1: &'a i32, val2: &'a i32 ) -> &'a i32 {
    return if *val1 > *val2 { val1 } else { val2 };
}

fn main() {
    let x = 1;
    let result;
    
    {
        let y = 10;
        result = max(&x, &y);
    }

    println!("{}", result);
}
error[E0597]: `y` does not live long enough
  --> Main.rs:11:26
   |
11 |         result = max(&x, &y);
   |                          ^^ borrowed value does not live long enough
12 |     }
   |     - `y` dropped here while still borrowed
13 | 
14 |     println!("{}", result);
   |                    ------ borrow later used here

error: aborting due to previous error

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

这次它变成了一个错误“`y` can not live long”。

我将'a添加到所有参数和返回值,意思是“所有参数和返回值具有相同的生命周期'a”。因此,两个参数中较短者的生命周期(本例中为 y 的生命周期)也应用于返回值,从而导致错误。

作为补充,我认为在互联网上的示例中,'a'b'static 是终身使用的。 'static 具有“只要程序运行就有效的值的引用”的特殊含义,即最长生命周期,但除此之外任何名称似乎都可以。

简而言之

fn max<'shortest_lifetime>( val1: &'shortest_lifetime i32, val2: &'shortest_lifetime i32 ) -> &'shortest_lifetime i32 {
    return if *val1 > *val2 { val1 } else { val2 };
}

这可以。

正如预期的那样关键词没用,但'i32 很好。

_

在 C 语言中,它可能仅在以蛇形情况编写变量、函数名等时使用。

C。

int some_val = 123;

除了 変数・関数名 等之外,Rust 还使用 「無視」パターン束縛整数リテラル 等。

“忽略”模式绑定

有很多图案

fn main() {
    let x = 10;

    match x {
        0 => println!("x is 0."),
        1 => println!("x is 1."),
        _ => println!("x is other.")
    }
}

最初用于match式。这就像switch文default

fn foo(_: i32) {
    println!("繰り返すだけ");
}

fn main() {
    let x = [1, 2, 3, 4, 5];

    for _ in x {
        foo(0);
    }
}

然后你也可以像这样忽略整个 for 或参数值:

fn main() {
    let x         = 10;
    let warn      = 20;
    let _not_warn = 30;

    println!("{}", x);
}

Rust 会对未使用的变量发出警告,但如果您在变量名前加上 _,即使该变量未使用,您也不会收到警告。

整数字面量

fn main() {
    let a      = 1_000_000;
    let b: u32 = 0x8000_FFFA;

    println!("{}, {:X}", a, b);
}

整数文字可以用_ 分隔以提高可读性。

@

待定更多

|

待定更多

?

待定更多

#

待定更多

$

待定更多

()

待定更多

<>

待定更多

..

待定更多

->

待定更多

=>

待定更多

...

待定更多

综上所述

学习任何新语言时,不熟悉的符号可能会令人困惑。在搜索中很难找到符号,我什至不知道它们的名字。

我希望这篇文章可以作为 Rust 新手的指南……或者说它至少可以作为你搜索的触发器可能有点夸张。

原创声明:本文系作者授权爱码网发表,未经许可,不得转载;

原文地址:https://www.likecs.com/show-308626064.html