Rust 是 静态类型(statically typed)语言,也就是说在编译时就必须知道所有变量的类型。根据值及其使用方式,编译器通常可以推断出我们想要用的类型
在Rust中,每一个值都属于某一个数据类型,告知rust它被指定为何种数据以明确数据处理方式
Rust是静态强类型语言,所有的变量都有严格的编译期语法检查。
rust中使用let关键字声明局部变量,只能在作用域{}内声明定义使用
fn main() {
let x = 5; //操作系统给x分配一块空间,并且把5存放到这块空间里面,然后标记这块栈空间是不可用:也就是说从此这块内存只能不能写了
let addr = &x as *const i32 as usize; //操作系统给addr分配了一块只读不写的空间,空间里面存储着x的地址。
println!("The value of x is:{}, adder is {:X}", x, addr);
x = 6; //此处视图去修改x这块已经标记为不可变的内存空间,因此会出错
println!("The value of x is:{}, adder is {:X}", x, addr);
}
规则:Rust使用let声明变量, OS就会将变量绑定到一块存储了value的的内存空间上,并且这块空间只读不写。,也就是说let声明的变量的值是不可以改变的。
规则:Rust使用let mut声明局部变量, OS会就分配一块存储了value的可读可写的内存空间,也就是说,这个值是可以修改的
fn main() {
let mut x = 5;//let操作系统给x分配一块栈空间,并且把5存放到这块空间里面,然后标记这块栈空间是mut可读可写:也就是x是可以修改的
//注:let语句在此处引入了一个模式解构功能,不要把let mut看成一个组合,应该把mux x视为一个组合
let mut addr = &x as *const i32 as usize;
println!("The value of x is:{}, adder is {:X}", x, addr);
x = 6; //地址没变但是值变了
addr = &x as *const i32 as usize;
println!("The value of x is:{}, adder is {:X}", x, addr);
}
总结:
rust有自动类型推导的功能
let x = 5;
let mut y = 6;
let x = 5u8; //通过字面量推导
fn main() {
let play_score = [("jack", 20), ("july", 15), ("lily", 25)];
let plays:Vec<_> = play_score.iter()
.map(|&(play, _score)|{
play
})
.collect();
println!("{:?}", plays) //["jack", "july", "lily"]
}
也可以直接写出变量类型
let x:i32 = 5; //x被绑定为i32类型,它的值是5
let mut y:i32 = 6;
let x:i32 = 100;
- Rust变量声明时:要声明的变量前置,对它的类型描述后置
- 设计理由:在变量声明中,最重要的是变量本身,而类型只是一个附属的额外描述,并非必不可少的部分。Rust有自动类型推导的功能
1、Rust有自动类型推导功能,但是它仍然是静态类型语言:一个变量的类型必须在编译阶段就确定,而且无法更改
2、Rust只允许"局部变量/全部变量???"进行自动类型推导,不允许函数签名等推导类型
原因:函数签名如果使用自动类型推导,可能导致某个调用的地方使用方式发生变化,它的参数,返回值类型就发生变化,可能导致一系列错误。
规则:Rust变量必须先声明后使用
1、如果我们想要使用一个变量,就必须将这个变量名绑定到一个值上。使用变量之前必须初始化
fn main() {
let x:i32;
println!("{}", x) //error[E0381]: borrow of possibly uninitialized variable: `x`
}
2、为什么变量必须初始化之后才能被使用
尝试回答:Rust中,类型没有"默认构造函数",变量没有“默认值”。对于let x:i32; 如果没有显示赋值,它就没有被初始化。不像其他语言,会默认初始化为0
fn main() {
let x = 1; //作用域:从定义到下一个x
let mut addr = &x as *const i32 as usize;
println!("The value of x is:{}, adder is {:X}", x, addr);
let x = x + 1; //OS又重新分配了一个空间,这个空间的名字叫做x
addr = &x as *const i32 as usize;
println!("The value of x is:{}, adder is {:X}", x, addr);
let x = x * 2; //新创建一个叫做x的不可变变量
addr = &x as *const i32 as usize;
println!("The value of x is:{}, adder is {:X}", x, addr);
}
1、当再次使用 let 时,实际上创建了一个新变量,我们可以改变值的类型,但复用这个名字。
fn main(){
let spaces = "len"; //字符串类型
let spaces = spaces.len(); //数字类型
println!("spaces = {}", spaces); //3
}
2、同一个名字是可以多次绑定不同的值,但不建议这么做,因为它被重新绑定就必须重新确定一下它的定义,这可能会引起程序的混淆不清。
3、什么时候使用变量遮蔽
比如:对一个可变数组初始化[可读写]之后希望这个变量是只读的
fn main() {
let mut v = vec![1, 2, 3];
v.push(4);
let v = v; //从这里往下,v成了只读变量,可读写变量v已经被遮蔽,无法再访问
for i in v{
println!("{}", i)
}
}
比如:希望修改一个不可变变量
fn main() {
let v = vec![1, 2, 3];
let mut v = v;
v.push(4);
println!("{:?}", v)
}
但是还是不建议过度使用,甚至不要使用这个特性【因为我压根儿就没觉得这个有什么优点,当然个人之见】
let除了声明局部变量外,还具有模式解构的功能
fn main() {
let (x, z) = (1, 2);
println!("{}, {}", x, z);
}
上面这个是什么东西,w(゚Д゚)w,据说和模式有关
下面是定义一个元组
fn main() {
let y:(i32, i32) = (1, 2);
println!("{}", y.0);
}
Rust中使用static关键字声明静态变量
规则:声明常量使用 const 关键字而不是 let,并且必须注明值的类型
fn test(){
const MIN_POINT:u32 = 1006; //作用域{}可以访问
println!("const, MIN_POINT:{}", MIN_POINT)
}
规则:const声明的常量可以在任何作用域中声明,let声明的局部变量只能在{}内声明使用
const MAX_POINT:u32 = 100_100; //作用域:当前文件内
//常量的名称是 MAX_POINTS,值是 100,100
fn test(){
const MIN_POINT:u32 = 1006; //作用域:{}
println!("const,MAX_POINT:{}; MIN_POINT:{}", MAX_POINT, MIN_POINT)
}
fn main() {
test();
println!("const,MAX_POINT:{}", MAX_POINT)
}
规则:常量的初始化表达式一定要是一个编译器常量,不能是运行期值
规则:常量绝对不能使用mut修饰,因为mut是用来声明可变局部变量的。
规则:常量的初始化表达式一定要是一个编译器常量,不能是运行期值
规则:const常量没有类似let局部变量那样的模板匹配功能,不能是运行期值
1、const常量与static静态变量区别
2、Rust 常量的命名规范是使用下划线分隔的大写字母单词,并且可以在数字字面值中插入下划线来提升可读性
参考:https://kaisery.github.io/trpl-zh-cn/ch03-02-data-types.html
https://kaisery.gitbooks.io/rust-book-chinese/content/content/Primitive%20Types%20%E5%8E%9F%E7%94%9F%E7%B1%BB%E5%9E%8B.html
《深入浅出Rust》