基本类型--布尔&字符类型&单元类型&函数(3)

rust学习-4

这里会继续整理rust中的基础数据类型,包括:布尔类型,字符类型还有单元类型,当然也会再把函数声明的部分简单带过,相信在学习rust之前大家也都接触过其他语言,本节也就一笔带过,简单了解就行,哈哈。

布尔类型

布尔类型,没啥多说的,就是我们见到的bool,在大多数语言里面都是用这个来进行声明的,当然某些语言比如java用的就是boolean
布尔类型只有两个值:true or false
样例代码:

fn main() {
    let _t = true;

    let f: bool = false; // 使用类型标注,显式指定f的类型
    println!("f = {}", f);
    if f {
        println!("当前f的值是false,不是true呢");
    }
}

在这里插入图片描述

字符类型

字符类型顾名思义,就是单个字符的类型,使用char来进行定义。学习过C语言等这些相对有些年限的语言的话,大家第一时间想到的是char就是ASCII里面的单个字符是char,即只占用一个字节的是一个字符,不过在rust里面,可能定位更广泛一点,unicode字符集为例,它实际上一个字符占用4个字节,但是在rust里面也可以认为是一个字符,可以先看看代码瞅瞅:

fn main() {
    use std::any::type_name_of_val;
    let a = 'a';
    let b = '波';
    let c = '🤩';
    println!("a = {}\tb={}\tc={}", a, b, c);
    println!("字符{}的类型是{}占用了{}字节的内存大小",a, type_name_of_val(&a), std::mem::size_of_val(&a));
    println!("字符{}的类型是{}占用了{}字节的内存大小",b, type_name_of_val(&b), std::mem::size_of_val(&b));
    println!("字符{}的类型是{}占用了{}字节的内存大小",c, type_name_of_val(&c), std::mem::size_of_val(&c));
}

在这里插入图片描述

我们可以清楚的看到,我们定义的都是char类型,打印出来的占用内存的大小确实4字节;为什么会这样呢。我查了一些资料后发现,rust语言中字符是Unicode类型,因此每个字符占用了4字节的空间,也就是说 rust的字符可以表示 从U+0000 ~ U+D7FFU+E000 ~ U+10FFFF的 可以表示的更多,但是在字符串中使用的确实Utf-8编码,也就是字符串中的字符所占的字节数是变化的(1 - 4),这样有助于大幅降低字符串所占用的内存空间。使用utf-8也就导致了一个问题是我们没办法使用下标的方式去获取某一个位置的字符

// c++中很常见的字符串定义与索引操作
#include <cstring>
int mian(){
	string a = "helloworld";
	printf("%c",a[1]);
}

上面这段在C++里面极其常见的代码,在rust中就行不通了;

 let a = "hello world";
    println!("a = {}", a);
    println!("a[1] = {}", a[1]);

在这里插入图片描述
运行以后我们发现确实是没办法的,但是却给出了我们解决办法,目前还没有学习到字符串,也就不说太多当做一个todo吧。

单元类型

单元类型,没啥说的就是(), 他唯一的值也是() , 多方查阅了资料后发现,其实这个玩意儿在某种程度可以类似C语言里面的void,因为在一个函数没有返回值的时候会默认返回一个这东西。同时,它也可以作为map的值,当我们不关注map中的值,只关注key的时候就可以这样用,类似golang中的struct{} , 可以用来占位,但是不占用任何内存。
看了一篇stackoverflow上帖子stackoverflow对rust中单元类型的解释
以下是几点总结:

  • 单元类型()类似c/c++/java语言中的void。当一个函数并不需要返回值的时候,c/c++/java中函数返回void,rust则返回()。但语法层面上,void仅仅只是一个类型,该类型没有任何值;而单位类型()既是一个类型,同时又是该类型的值
  • 单元类型()也类似c/c++/java中的null,但却有很大不同。 null是一个特殊值,可以赋给不可类型的值,例如java中的对象,c中指向struct实例的指针,c++中的对象指针。但在rust中,()不可以赋值给除单元类型外的其它的类型的变量,()只能赋值给()。
  • Rust标准库中使用单元类型()的一个例子是HashSet。一个HashSet只不过是HashMap的一个非常简单地包裹,写作:HashMap<T, ()>。HashMap的第二个泛型类型参数即用了单元类型()
  • 可以用Result<(), MyErrorType>代替Option,某些开发者认为Result<(), MyErrorType>语义上能更简明地表示一个“结果”。

函数

在了解函数之前,我们先了解下 表达式语句.
在最开始我也是一脸懵,语句和表达式感觉一样呢?后来才发现,这玩意儿在rust中就是两个东西。
语句就是单纯的一个函数语句,但是表达式就不一样了,表达式总要返回值。这里我们可能更蒙了,函数不是有返回值么?怎么表达式要有返回值呢?
首先我们来看语句:

let a = 8;
let b: Vec<f64> = Vec::new();
let (a, c) = ("hi", false);

上面这些都是语句,用了几种方式,声明了几个变量。
但是如果我们这样let b = (let a = 8); 那就会报错了。
在这里插入图片描述
以上错误告诉我们,let是一个语句,不是一个表达式,因此它不返回值,也就不能给其它变量赋值.

表达式

表达式会进行求值,然后返回一个值。例如 5 + 6,在求值后,返回值 11,因此它就是一条表达式。

表达式可以成为语句的一部分,例如 let y = 6 中,6 就是一个表达式,它在求值后返回一个值 6(有些反直觉,但是确实是表达式)。

调用一个函数是表达式,因为会返回一个值,调用宏也是表达式,用花括号包裹最终返回一个值的语句块也是表达式,总之,能返回值,它就是表达式:

fn main() {
    let y = {
        let x = 3;
        x + 1
    };
    println!("The value of y is: {}", y);
}

在这里插入图片描述
上面的代码中就是使用了语句块表达式将值赋给了y
语句块如下:

{
    let x = 3;
    x + 1
}

该语句块是表达式的原因是:它的最后一行是表达式,返回了 x + 1 的值,注意 x + 1 不能以分号结尾,否则就会从表达式变成语句, 表达式不能包含分号。这一点非常重要,一旦你在表达式后加上分号,它就会变成一条语句,再也不会返回一个值,请牢记!

最后,表达式如果不返回任何值,会隐式地返回一个 () 。

fn main() {
    use std::any::type_name_of_val;
    let res = ret_unit_type();
    println!("The value of y is: {}", type_name_of_val(&res));
}
fn ret_unit_type() {
    let x = 1;
    // if 语句块也是一个表达式,因此可以用于赋值,也可以直接返回
    // 类似三元运算符,在Rust里我们可以这样写
    let _y = if x % 2 == 1 {
        "odd"
    } else {
        "even"
    };
    // 或者写成一行
    let z = if x % 2 == 1 { "odd" } else { "even" };
    println!("z = {}", z);
}

在这里插入图片描述
我们可以看到,如果最后是加了分号 ;以后,就会变成语句,整个函数的返回值就会变成默认的也就是 ()类型。

函数

在其他语言里面我们已经接触过函数了,在rust中跟其他语言也没有什么不同,只是在声明和默认返回值上可能会有不同,我们简单了解下就行
函数声明

fn fun1(i: i32, j: i32) -> i32 {
   i + j
 }

在这里插入图片描述
这张图可以完美的解释rust中如何声明一个函数的、

  • 函数名和变量名使用蛇形命名法(snake case),例如 fn add_two() -> {}
  • 函数的位置可以随便放,Rust 不关心我们在哪里定义了函数,只要有定义即可
  • 每个函数参数都需要标注类型
参数的声明

在声明一个函数的时候,参数类型都必须要显示的写明,不写或者漏写,都会报错,当然也不能像golang那样相同的类型只在后面写一个类型,类似:func add(a ,b int32) int32{} 这样也是有问题的

fn add(x , y : i32){
    println!("The value of x is: {}", x);
    println!("The value of y is: {}", y);
}

在这里插入图片描述

最终的报错就是这样的。

函数的返回值

在rust中,函数的返回值有两种,一种是通过上面所提到的表达式的方式来进行返回值,就是结尾不加分号,另一种就是 通过return 来进行返回值。

fn plus_or_minus(x:i32) -> i32 {
    if x > 5 {
        return x - 5
    }

    x + 5
}

fn main() {
    let x = plus_or_minus(5);

    println!("The value of x is: {}", x);
}
特殊类型的返回值

rust中有一种特殊类型的返回值,就是单元类型,

  • 函数没有返回值,那么返回一个 ()
  • 通过 ; 结尾的语句返回一个 ()
    具体的就不进行演示了,在上面的代码中,有提到返回值为单元类型的代码。
永不返回的发散函数

当用 ! 作函数返回类型的时候,表示该函数永不返回( diverge function ),特别的,这种语法往往用做会导致程序崩溃的函数:

fn dead_end() -> ! {
  panic!("你已经到了穷途末路,崩溃吧!");
}

或者死循环的

fn forever() -> ! {
  loop {
    //...
  };
}

好的,写到这里,也到了本节的尾声了,本章加上上一章介绍了rust中的基本类型,也有一些代码演示,可能还有更多的东西需要我们来深入挖掘,这里也比较浅显,等后面学的更多使用的更多的时候,再回来补充下本文。感谢阅读~

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值