变量与数据类型

变量与数据类型_第1张图片

专栏简介:本专栏作为Rust语言的入门级的文章,目的是为了分享关于Rust语言的编程技巧和知识。对于Rust语言,虽然历史没有C++、和python历史悠远,但是它的优点可以说是非常的多,既继承了C++运行速度,还拥有了Java的内存管理,就我个人来说,还有一个优点就是集成化的编译工具cargo,语句风格和C++极其相似,所以说我本人还是比较喜欢这个语言,特此建立这个专栏,作为学习的记录分享。

日常分享:每天努力一点,不为别的,只是为了日后,能够多一些选择,选择舒心的日子,选择自己喜欢的人!

变量与数据类型_第2张图片


目录

Rust中的变量

可变变量

不可变变量

常量

隐藏

数据类型

标量类型

整型

浮点型

布尔型

字符类型

复合类型

元组类型

数组类型

总结


Rust中的变量

相信熟悉c++或者其他编程语言的,都会很熟悉变量这个词,变量作为暂时存储数值的容器,不过在Rust中,变量默认是不可变的。这个特性和Rust的性质是有关系的。虽然说是叫变量,但是又是不可变的,这是由于一个所有权的原因,这个问题留到后面细细讲解。

可变变量

变量的声明关键字是:let

如果是要声明可变变量,则添加关键字mut.


fn main() {
    let mut rng = 10;
    println!("rng的为: {}", rng);
    rng=20;
    println!("rng的为: {}", rng);
    
}

可以看到这里变量rng的值可以再次赋值,不会出现报错。

不可变变量

不可变变量的定义就是可变变量没有mut关键字,不能二次赋值。

变量与数据类型_第3张图片

我们发现这里出现了报错,不允许二次对变量rcg赋值,这代表就是不可变变量。

常量

类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,不过常量与变量还是有一些区别。

首先,不允许对常量使用 mut。常量不光默认不可变,它总是不可变。声明常量使用 const 关键字而不是 let,并且 必须 注明值的类型。在下一部分,“数据类型” 中会介绍类型和类型注解,现在无需关心这些细节,记住总是标注类型即可。

常量可以在任何作用域中声明,包括全局作用域,这在一个值需要被很多部分的代码用到时很有用。

最后一个区别是,常量只能被设置为常量表达式,而不可以是其他任何只能在运行时计算出的值。这里和c++中的常量表达式十分相似。其实简单的说就是常量在编译时就必须获得值,而不是在运行过程中才能获得值。下面举几个例子:

const THETA_COUNT: usize =30*1024;
    println!("THETA_COUNT: {}", THETA_COUNT);

 这里定义了一个常量,是30*1024,结果运行成功,这是因为在编译时就已经计算出了确切的值,我们再看另一个例子:


fn main() {
    const THETA_COUNT2:usize=get_value_count();
    println!("THETA_COUNT2: {}", THETA_COUNT2);
}
fn get_value_count() -> usize {
    let count =30;
    return count;
}

 error[E0015]: cannot call non-const fn `get_value_count` in constants

最后结果报错,显示不能由函数转化成常量。这就是常量的特性,只能由在编译时能获的确切值的表达式组成。

隐藏

前面提到的可变变量,虽然可以二次赋值,但是需要声明是可变变量,除此之外,Rust还有一种方式可以改变变量的值——隐藏。

我们可以定义一个与之前变量同名的新变量。Rustacean 们称之为第一个变量被第二个 隐藏(Shadowing) 了,这意味着当您使用变量的名称时,编译器将看到第二个变量。实际上,第二个变量“遮蔽”了第一个变量,此时任何使用该变量名的行为中都会视为是在使用第二个变量,直到第二个变量自己也被隐藏或第二个变量的作用域结束。可以用相同变量名称来隐藏一个变量,以及重复使用 let 关键字来多次隐藏。


fn main() {
    let args=10;
    println!("args: {}", args);
    let args=args*args;
    println!("args: {}", args);
    {
        let args=20;
        println!("args: {}", args);
    }
    println!("args: {}", args);
}


 这里先是将args绑定到10上,接着通过关键字let创建一个新变量args,args的值就变成100,然后在花括号创建的域内,let关键字将args创建一个新变量,赋值为20,第三个let只在域内起作用,花括号之外的的值依旧是原本的值,运行的结果:

Finished dev [unoptimized + debuginfo] target(s) in 0.29s
     Running `target/debug/Rust`
args: 10
args: 100
args: 20
args: 100

看到这里,因该有小伙伴发现隐藏和可变变量似乎一样,其实还是存在差异,隐藏是创建了一个新变量,而可变变量的数据类型是不能变得,只能由定义时的数据类型决定。


fn main() {
   let str="hello";
   let length=str.len();
   println!("length is {}",length);
   let mut buffer="Hello, world!";
   buffer=buffer.len()+2;
   println!("buffer is {}",buffer);
}


变量与数据类型_第4张图片

这里显示报错,所以说隐藏和可变变量的区别就是数据类型是否可以变化。

数据类型

在 Rust 中,每一个值都属于某一个 数据类型data type),这告诉 Rust 它被指定为何种数据,以便明确数据处理方式。我们将看到两类数据类型子集:标量(scalar)和复合(compound)。

Rust语言是一种静态类型(statically typed)语言,也就是说在编译时就必须知道所有变量的内型,这点和python不一样,python是动态类型语言,其内使用的所有变量不需要指明数据类型。但是一般来说,编译器是可以推断出变量的数据类型,但是如果数据类型转换过于复杂,那就需要你去注释。
 

fn main(){

let sm=String::from("hello");

let num:usize=sm.parse().expect("not number");

println!("{}",num);

}

 这里的num变量的数据类型必须标注,如果不标注就无法编译通过,这也就再次证明了静态型语言的特点。

标量类型

在高中物理中有提到过标量和矢量,当时的标量是指一个没有方向只有大小的值,但是,这里的标量指的是单独的一个变量。用官方语言来解释就是:标量scalar)类型代表一个单独的值。。

Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型。

整型

整数是一个没有小数的数字他分为无符号整型和有符号整型。

长度 有符号 无符号
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize

 每一个变体都可以是有符号或无符号的,并有一个明确的大小。有符号无符号 代表数字能否为负值,换句话说,这个数字是否有可能是负数(有符号数),或者永远为正而不需要符号(无符号数)。

每一个有符号的变体可以储存包含从 -(2n - 1) 到 2n - 1 - 1 在内的数字,这里 n 是变体使用的位数。所以 i8 可以储存从 -(27) 到 27 - 1 在内的数字,也就是从 -128 到 127。无符号的变体可以储存从 0 到 2n - 1 的数字,所以 u8 可以储存从 0 到 28 - 1 的数字,也就是从 0 到 255。

另外,isizeusize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的,32 位架构上它们是 32 位的。

Rust的默认类型为i32,当你不知道使用什么类型的时候,就是用默认的数据类型。

浮点型

和其他语言也一样,Rust也有浮点数,只不过不像c++那样分为float和double两种类型,但是也是由双精度(f64)和单精度(f32)两种类型组成。Rust默认的是64位。


fn main() {
    let x=45.6;
    let y:f32=44.6;
    println!("x:{},y:{}",x,y);
 }
 
 
 

 浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数。

布尔型

和C++语言一样,Rust也有布尔类型,true,false。数值类型是bool.


fn main() {
   let flag=true;
   let flags:bool = false;
   
 }

 布尔类型主要场景还是用在控制流方面。作为一个判断条件。

字符类型

Rust语言的char类型和其他语言一样,但是优点就是通用性比较好,就连一些表情都是可以进行存储的。


 
fn main() {
  let c='c';
  println!("c is {}",c);
  let a='';
  println!("a is {}",a);
    
}

Rust语言的cahr类型的大小为四个字节,并代表一个Unicode标量值。比其他语言使用ASCII表示的内容多。所以这也是Rust的一个优点。

复合类型

复合类型就是指多个值合成一个复合类型。Rust中有元组和数组两种符合类型。

元组类型

学习过python的应该都知道,元组是一种将多个其他类型的值组合成一个复合类型的主要方式。元组的特性就是长度不能改变,一旦定义,就不能再更改元组的长度。注意,这里的元组和Python中的元组定义不一样。这里只是说元组的长度不变。

fn main() {
  let tup:(f32,f64,i32)=(0.9,3.42,20);
    
}

tup变量绑定到在整个元组上, 元组是一个复合函数,我们可以用模式匹配来进行获得元组中的值,模式匹配后面会更详细的介绍,这里就只是使用。

 
fn main() {
  let mut tup:(f32,f64,i32)=(0.9,3.42,20);
  //tup.1=0.8;
  let (x,y,z)=tup;
  println!("{} {} {}",x,y,z);   
}

这里使用的方法是解构方法。

除了解构方法,还有一种方式就是索引。不过和其他语言不同的是,不再需要[]号来存放下标。


fn main() {
  let tup:(i32,f32,usize) =(32,34.8,89);
  println!("The first number is {}",tup.0);
  println!("The second number is {}",tup.1);
  println!("The thrid number is {}",tup.2);
}

上面说的,元组的值可以改变,不过只有定义元组为可变变量时,才能够改变元组的值。这里我来举个例子。


 
fn main() {
  let mut rng:(i32,i64,isize)=(23,34,90);
  rng.1=30;
  println!("{},{},{}",rng.0,rng.1,rng.2);  
}

注意: 不带任何值的元组有个特殊的名称,叫做 单元(unit) 元组。这种值以及对应的类型都写作 (),表示空值或空的返回类型。如果表达式不返回任何其他值,则会隐式返回单元值。

数组类型

另一个包含多个值的方式是 数组array)。与元组不同,数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同,Rust 中的数组长度是固定的。

fn main() {
  let arr=[1,2,3,4,5,6,7,8,9,10 ,10,11,12,13,14,15,16,17];
}

 数组的空间是在栈上开辟的,他的使用主要就是在确定好元素的个数,数据类型的时候用比较好。其他的时候,用Vector比较好。这个我们放在后面讲解,学习过c++的应该知道这个。下面我们来看一下数组的定义有几种方式以及如何去访问。

fn main() {
  let arr=[1,2,3,4,5,6,7,8,9,10 ,10,11,12,13,14,15,16,17];//传统的定义
  println!("{},{},{},{}",arr[0],arr[1],arr[2],arr[3]);
  let arr1:[i32;5]=[1,2,3,4,5]; //声明5个i32数据类型的数组
  println!("{},{},{},{}",arr1[0],arr1[1],arr1[2],arr1[3]);
  let arr2=[3;5]; //创建5个数据的数组,且每个元素都是3; 3为数组起始值,5为个数.
  println!("{},{},{}",arr1[0],arr1[1],arr1[2]);

}

变量与数据类型_第5张图片

 

总结

本节的内容就到此结束了,这届主要讲的就是Rust中的变量以及一些数据类型,这一节的难度不是很大,只要认真看,很快就能学会。所以,这里就不过多介绍了,我们下节见!

你可能感兴趣的:(Rust编程,rust)