rust abc(2): 从 hello world 到整数、浮点类型

在这里插入图片描述

1. 目的

通过一些微型的 rust 样例代码, 学习 rust 的基本语法,以及整数、浮点数类型的初步使用。

2. 搞懂 hello world

2.1 代码

使用 cargo new hello-rust 创建的工程中,代码如下:

fn main()
{
    println!("Hello, world!");
}

2.2 fn 的含义

rust 的一个关键字。表示函数

2.3 main() 的含义

函数名称, 也是程序入口点。相当于C/C++可执行程序的 main() 函数.

尝试把 main() 改为 main2():

fn main2() {
    println!("Hello, world!");
}

编译会报错:

zz@Legion-R7000P% cargo run
   Compiling hello-rust v0.1.0 (/home/zz/work/rust_abc/hello-rust)
error[E0601]: `main` function not found in crate `hello_rust`
 --> src/main.rs:3:2
  |
3 | }
  |  ^ consider adding a `main` function to `src/main.rs`

For more information about this error, try `rustc --explain E0601`.
error: could not compile `hello-rust` (bin "hello-rust") due to previous error

2.4 println! 的含义

println! 是 rust 语言预定义的一个宏。rust 语言中的宏是以 ! 结尾。可以暂时把 rust 的宏理解为 “函数的加强版”。

2.5 行尾分号是必要的吗?

乍一看, println! 这句去掉分号也能运行:

fn main() {
    println!("Hello, world!")
}

但 rust 中的分号的含义是: 压制表达式的结果。也就是说,如果表达式结尾没有分号, 那么表达式(的返回值)就会被返回。

举一个和是否用;导致不同结果的例子:

let a = {
    let inner = 2;
    inner * inner
};

let b = {
    let inner = 2;
    inner * inner;
};

其中 a 的值将为4, 而 b 的类型并不是整数类型。

zz@Legion-R7000P% cat src/main.rs
fn main() {
    println!("Hello, world!");
    let a = {
        let inner = 2;
        inner * inner
    };
    println!("{}", a);

}
zz@Legion-R7000P% cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/hello-rust`
Hello, world!
4
zz@Legion-R7000P% cat src/main.rs
fn main() {
    println!("Hello, world!");
    let a = {
        let inner = 2;
        inner * inner
    };
    println!("{}", a);

    let b = {
        let inner = 2;
        inner * inner;
    };
    println!("{}", b);
}
zz@Legion-R7000P% cargo run
   Compiling hello-rust v0.1.0 (/home/zz/work/rust_abc/hello-rust)
error[E0277]: `()` doesn't implement `std::fmt::Display`
  --> src/main.rs:13:20
   |
11 |         inner * inner;
   |                      - help: remove this semicolon
12 |     };
13 |     println!("{}", b);
   |                    ^ `()` cannot be formatted with the default formatter
   |
   = help: the trait `std::fmt::Display` is not implemented for `()`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0277`.
error: could not compile `hello-rust` (bin "hello-rust") due to previous error

2.6 左花括号可以放下一行吗?

fn main()
{
    println!("Hello, world!")
}

实际编译运行了下, 可以使用的; 不过 rustfmt 则要求说应该放在同一行1

为了保持代码结构的良好可读性,Rust 中定义各种语言项,包括控制结构(if / match 等)、函数、结构体、枚举等,要求左花括号与其定义保持同一行。

3. 数据类型的例子

3.1 代码

代码来自23:
data_type.rs:

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

fn main() {
    let food = "清蒸螃蟹"; // string 字符串类型
    let price = 7767517; // float 类型
    let checked = true; // boolean 类型

    println!("food is {}", food);
    print_type_of(&food);
    println!("price is {}", price);
    print_type_of(&price);
    println!("checked is {}", checked);
    print_type_of(&checked);
}

3.2 rust 的注释

Rust 中的注释方式与其它语言(C、Java)一样,支持两种注释方式:

// 这是第一种注释方式

/* 这是第二种注释方式 */

/*
 * 多行注释
 * 多行注释
 * 多行注释
 */

个人比较习惯 // 作为注释符号, 因此在 ~/.vimrc 中的注释快捷键命令里进行配置:

"-- prepend comment chars in each line
" https://vi.stackexchange.com/questions/8128/how-to-toggle-comments-with-ctrl
noremap <C-m> :<S-Left>exe "<S-Right>normal! I".b:commentType<CR>
" autocmd BufReadPost *.[ch] let b:commentType='// '
autocmd FileType c let b:commentType='// '
autocmd FileType cpp let b:commentType='// '
autocmd FileType python let b:commentType='# '
autocmd FileType cmake let b:commentType='# '
autocmd FileType vim let b:commentType='" '
autocmd FileType rust let b:commentType='// '

3.3 编译运行结果

rustc data_type.rs
./data_type
food is 清蒸螃蟹
&str
price is 7767517
i32
checked is true
bool

Rust 是一个静态的严格数据类型的语言。每个值都有唯一的数据类型,要么是整型,要么是浮点型等等。

Rust 语言在赋值时并不强制要求指定变量的数据类型,Rust 编译器可以根据分配给它的值自动推断变量的数据类型。

上面的代码中,我们并没有为每一个变量指定它们的数据类型。Rust 编译器会自动从 等号 = 右边的值中推断出该变量的类型。例如 Rust 会自动将 双引号 阔起来的数据推断为 字符串,把没有小数点的数字自动推断为 整型。把 true 或 false 值推断为 布尔类型。

3.4 基本数据类型

Rust 语言中有四种标量数据类型:

  • 整型
  • 浮点型
  • 布尔类型
  • 字符类型

4. 整数类型的例子

let price = 100; 默认类型是 i32.

4.1 代码

int_types.rs:

fn main() {
    let price = 100;
    let price2:u32 = 200;
    let price3:i32 = -300;
    let price4:isize = 400;
    let price5:usize = 500;

    println!("price is {}", price);
    println!("price2 is {} and price3 is {}", price2, price3);
    println!("price4 is {} and price5 is {}", price4, price5);

    let price6:i32 = 66.66;
    let price7:i8 = 192;
}

其中 let price6:i32 = 66.66 在编译时就报错了, 原因是等号左右两侧的数据类型不匹配:

zz@Legion-R7000P% rustc int_types.rs
error[E0308]: mismatched types
  --> int_types.rs:12:22
   |
12 |     let price6:i32 = 66.66;
   |                ---   ^^^^^ expected `i32`, found floating-point number
   |                |
   |                expected due to this

error: aborting due to previous error

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

4.2 还是代码

这次把刚刚报错的 price6 一行注释掉。

fn main() {
    let price = 100;
    let price2:u32 = 200;
    let price3:i32 = -300;
    let price4:isize = 400;
    let price5:usize = 500;

    println!("price is {}", price);
    println!("price2 is {} and price3 is {}", price2, price3);
    println!("price4 is {} and price5 is {}", price4, price5);

    //let price6:i32 = 66.66;
    let price7:i8 = 192;
}

编译运行, 发现 price7 这行报错了, 原因是等号右侧的值 192 超过了等号左侧数据范围 [ − 128 , 127 ] [-128, 127] [128,127]

zz@Legion-R7000P% rustc int_types.rs
warning: unused variable: `price7`
  --> int_types.rs:13:9
   |
13 |     let price7:i8 = 192;
   |         ^^^^^^ help: if this is intentional, prefix it with an underscore: `_price7`
   |
   = note: `#[warn(unused_variables)]` on by default

error: literal out of range for `i8`
  --> int_types.rs:13:21
   |
13 |     let price7:i8 = 192;
   |                     ^^^
   |
   = note: the literal `192` does not fit into the type `i8` whose range is `-128..=127`
   = help: consider using the type `u8` instead
   = note: `#[deny(overflowing_literals)]` on by default

error: aborting due to previous error; 1 warning emitted

4.3 整数类型的最大值、最小值

fn main() {
    println!("std::u128::MAX is {}, std::i128::MAX is {}, std::i128::MIN is {}", std::u128::MAX, std::i128::MAX, std::i128::MIN);
    println!("std::u64::MAX is {}, std::i64::MAX is {}, std::i64::MIN is {}", std::u64::MAX, std::i64::MAX, std::i64::MIN);
    println!("std::u32::MAX is {}, std::i32::MAX is {}, std::i32::MIN is {}", std::u32::MAX, std::i32::MAX, std::i32::MIN);
    println!("std::u16::MAX is {}, std::i16::MAX is {}, std::i16::MIN is {}", std::u16::MAX, std::i16::MAX, std::i16::MIN);
    println!("std::u8::MAX is {}, std::i8::MAX is {}, std::i8::MIN is {}", std::u8::MAX, std::i8::MAX, std::i8::MIN);
}
zz@Legion-R7000P% ./int_types 
std::u128::MAX is 340282366920938463463374607431768211455, std::i128::MAX is 170141183460469231731687303715884105727, std::i128::MIN is -170141183460469231731687303715884105728
std::u64::MAX is 18446744073709551615, std::i64::MAX is 9223372036854775807, std::i64::MIN is -9223372036854775808
std::u32::MAX is 4294967295, std::i32::MAX is 2147483647, std::i32::MIN is -2147483648
std::u16::MAX is 65535, std::i16::MAX is 32767, std::i16::MIN is -32768
std::u8::MAX is 255, std::i8::MAX is 127, std::i8::MIN is -128

5. 浮点类型

5.1 不能给浮点类型赋值为整数

fn main() {
    let price8:f64 = 99; // compile error
}
zz@Legion-R7000P% rustc float_types.rs
error[E0308]: mismatched types
 --> float_types.rs:2:22
  |
2 |     let price8:f64 = 99; // compile error
  |                ---   ^^
  |                |     |
  |                |     expected `f64`, found integer
  |                |     help: use a float literal: `99.0`
  |                expected due to this

error: aborting due to previous error

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

5.2 浮点类型赋值

默认是 float64 类型。

rust 允许数字的表示中含有下划线,相当于打印版数字中的逗号

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

fn main() {
    //let price8:f64 = 99; // compile error
    let price9 = 18.00;
    print_type_of(&price9);
    
    let price10:f32 = 8.88;
    let price11:f64 = 168.125;

    println!("price9 {}", price9);
    println!("price10 {}", price10);
    println!("price11 {}", price11);

    // rust 允许数字的表示中含有下划线,相当于打印版数字中的逗号
    let price12 = 1_000_000;
    println!("price12 {}", price12);

    let price13 = 1_000_000.666_123;
    println!("price13 {}", price13);
}
zz@Legion-R7000P% rustc float_types.rs
zz@Legion-R7000P%       ./float_types 
f64
price9 18
price10 8.88
price11 168.125
price12 1000000
price13 1000000.666123

6. References


  1. P.FMT.04 语言项(Item) 定义时左花括号(brace)位置应该与语言项保持同一行 ↩︎

  2. 第 4 章 Rust 的数据类型 ↩︎

  3. 如何在Rust中打印一个变量的类型?《跟星哥一起学RUST语言》 ↩︎

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值