1、定义变量
1. 不可变绑定
1. 自动类型推导
fn main() {
let a1 = 5; // 自动推导数据类型i32
let a2:i32 = 5; // 指定数据类型i32
}
2. 不可对变量重新[赋值]
fn main() {
let a1 = 5; // 自动推导数据类型i32
a1 = 10; // error: cannot assign twice to immutable variable `a1`
}
error[E0384]: cannot assign twice to immutable variable `a1`
--> main.rs:14:3
|
11 | let a1 = 5; // 自动推导数据类型i32
| -- first assignment to `a1`
...
14 | a1 = 10;
| ^^^^^^^ cannot assign twice to immutable variable
2. 可变绑定
1. 可以对变量重新赋值
fn main() {
// 在声明变量时,在变量前面加入 mut 关键字,变量就会成为可变绑定的变量
let mut a: f64 = 1.0;
println!("{:?}", a);
//改变变量a的值
a = 2.0;
println!("{:?}", a);
}
➜ main make
rustc main.rs
./main
1.0
2.0
➜ main
2. 也可以对变量重新绑定
fn main() {
// 在声明变量时,在变量前面加入 mut 关键字,变量就会成为可变绑定的变量
let mut a: f64 = 1.0;
println!("{:?}", a);
// 重新绑定为不可变
let a1 = a;
println!("{:?}", a1);
// 重新绑定为可变
let mut a2 = a;
println!("{:?}", a2);
}
➜ main make
rustc main.rs
warning: variable does not need to be mutable
--> main.rs:3:7
|
3 | let mut a: f64 = 1.0;
| ---^^
| |
| help: remove this `mut`
|
= note: #[warn(unused_mut)] on by default
warning: variable does not need to be mutable
--> main.rs:10:7
|
10 | let mut a2 = a;
| ---^^^
| |
| help: remove this `mut`
./main
1.0
1.0
1.0
➜ main
会报警高,但是正常运行。
3. 局部作用域
fn main() {
let long_lived_binding = 1;
// 局部作用域
{
let short_lived_binding = 2;
println!("inner short: {}", short_lived_binding);
let long_lived_binding = 5_f32;
println!("inner long: {}", long_lived_binding);
}
// println!("outer short: {}", short_lived_binding); //error:short_lived_binding局部作用域内的变量
// FIXME ^ Comment out this line
println!("outer long: {}", long_lived_binding);
}
➜ main make
rustc main.rs
./main
inner short: 2
inner long: 5
outer long: 1
➜ main
4. 类型比较
Yes
fn main() {
let a1 = 5; // 自动推导数据类型i32
let a2:i32 = 5; // 指定数据类型i32
assert_eq!(a1, a2); // 比较a1与a2的【数据类型】是否一致
}
➜ main make
rustc main.rs
./main
➜ main
fn main() {
let a1:u32 = 5;
let a2:i32 = 5;
assert_eq!(a1, a2);
}
➜ main make
rustc main.rs
error[E0308]: mismatched types
--> main.rs:4:3
|
4 | assert_eq!(a1, a2);
| ^^^^^^^^^^^^^^^^^^^ expected u32, found i32
2、基本数据类型
1. 基本使用
- 有符号整数:
i8
,i16
,i32
,i64
和isize
(指针大小) - 无符号整数:
u8
,u16
,u32
,u64
和usize
(指针大小) - 浮点:
f32
,f64
-
char
Unicode标值一样'a'
,'α'
和'∞'
(每4字节) -
bool
以及true
或false
fn main() {
// boolean type
let f1 = true;
let f2: bool = false;
println!("{:?}", f1);
println!("{:?}", f2);
// char type
let c = 'c';
println!("{:?}", c);
// numeric types
let x = 42;
let y: u32 = 123_456;
let z: f64 = 1.23e+2;
let zero = (z - 123.4).abs();
let bin = 0b1111_0000;
let oct = 0o7320_1546;
let hex : u32 = 0xf23a_b049;
println!("{:?}", x);
println!("{:?}", y);
println!("{:?}", z);
println!("{:?}", zero);
println!("{:?}", bin);
println!("{:?}", oct);
println!("{:?}", hex);
}
➜ main make
rustc main.rs
./main
true
false
'c'
42
123456
123.0
0.4000000000000057
240
15532902
4063932489
➜ main
2. isize、usize
- i8、i32 => int8、int32
- u8、u32 => uint8、uint32
- f32、f64 => float32、float64
- 数值如果不指定iN、uN、fN,则编译器自动使用
i32
为整数,f64
作为浮点数
fn main() {
let x1 = 1u8; // 告诉编译器使用 uint8 分配内存来存储 1
let x2 : u8 = 1; // 同上
let x3 = 1i8; // 告诉编译器使用 int8 分配内存来存储 1
let x4 : i8 = 1; // 同上
let y1 = 2u32; // 告诉编译器使用 uint32 分配内存来存储 2
let y2 : u32 = 2;
let y3 = 2i32; // 告诉编译器使用 uint32 分配内存来存储 1
let y4 : i32 = 2;
let z1 = 3f32; // 告诉编译器使用 float32 分配内存来存储 3
let z2 : f32 = 3f32;
let z3 : f64 = 3f64; // 告诉编译器使用 float64 分配内存来存储 3
let z4 = 9.9;
}
3. 类型转换
fn main() {
// float
let a = 65.4321_f32;
println!("{:?}", a);
// float => uint8
let b = a as u8;
println!("{:?}", b);
// uint8 => char
let c = b as char;
println!("{:?}", c);
}
➜ main make
rustc main.rs
./main
65.4321
65
'A'
➜ main
3、字符串
1. &str => 不可变字符数组
1. 基本使用
fn main() {
let str1 = "Hello, world!"; // 自动推导类型为 &str
let str2 : &str = "Hello, world!";
println!("str1 = {:?}", str1);
println!("&str1 = {:?}", &str1);
println!("str2 = {:?}", str2);
println!("&str2 = {:?}", &str2);
}
➜ main make
rustc main.rs
./main
str1 = "Hello, world!"
&str1 = "Hello, world!"
str2 = "Hello, world!"
&str2 = "Hello, world!"
➜ main
2. &str内部的地址
fn main() {
let mystr :&str = "abcd";
println!("mystr address: {:p}", &mystr);
println!("mystr address: {:p}", &mystr[0..]);
println!("mystr address: {:p}", &mystr[1..]);
println!("mystr address: {:p}", &mystr[2..]);
println!("mystr address: {:p}", &mystr[3..]);
}
➜ main make
rustc main.rs
./main
mystr address: 0x7fff52bd45e0
mystr address: 0x10d071040
mystr address: 0x10d071041
mystr address: 0x10d071042
mystr address: 0x10d071043
➜ main
- mystr 与 mystr[i] 内存地址段明显不一样
- mystr => 存储在局部栈帧
- mystr[i] => 常量字符存储在符号表中
2. string => 可变字符数组
fn main() {
let info1 = String::from("hello");
println!("info1 = {:?}", info1);
let info2 : String = String::from("hello");
println!("info2 = {:?}", info2);
}
➜ main make
rustc main.rs
./main
info1 = "hello"
info2 = "hello"
➜ main
3. String 的内存结构
let s1 =String::from("hello");
[图片上传失败...(image-deab1b-1534067123291)]
&str的内存结构差不多,只是不可变的。
4. &str => string
fn main() {
let str1 = "hello".to_string();
println!("str1 = {:?}", str1);
let str2 : &str = "hello";
let str3 = str2.to_string();
println!("str3 = {:?}", str3);
}
➜ main make
rustc main.rs
./main
str1 = "hello"
str3 = "hello"
➜ main
5. string => &str
fn main() {
// String
let info = String::from("hello");
// &str 1
let info_str1 = info.as_str();
println!("info_str1 = {:?}", info_str1);
// &str 2
let info_str2 = &info;
println!("info_str2 = {:?}", info_str2);
}
➜ main make
rustc main.rs
./main
info_str1 = "hello"
info_str2 = "hello"
➜ main
6. string = string + &str
fn main() {
let info = String::from("hello");
let new = info + "world";
// println!("info = {:?}", info); //error: use of moved value: `info`
println!("new = {:?}", new);
}
➜ main make
rustc main.rs
./main
new = "helloworld"
➜ main
7. string push_str()、pop_str()
1. push
fn main() {
let mut info = String::from("hello");
println!("info = {:?}", info);
// 压入字符
info.push('-');
// 压入字符串
info.push_str("world");
println!("info = {:?}", info);
}
➜ main make
rustc main.rs
./main
info = "hello"
info = "hello-world"
➜ main
2. pop
fn main() {
let mut s = String::from("foo");
assert_eq!(s.pop(), Some('o'));
assert_eq!(s.pop(), Some('o'));
assert_eq!(s.pop(), Some('f'));
assert_eq!(s.pop(), None);
}
➜ main make
rustc main.rs
./main
➜ main
8. format
fn main() {
let str1 : &str = "hello";
let str2 : String = String::from("world");
let str3 = format!("{0} - {1}", str1, str2);
println!("str3 = {:?}", str3);
}
➜ main make
rustc main.rs
./main
str3 = "hello - world"
➜ main
9. &str、String 字符串切割
1. 只能对 &str、&String 进行切割
fn main()
{
// &str
let mystr:&str = "abcd";
println!("mystr :{:?}", &mystr[1..2]); //"bc"
println!("mystr :{:?}", &mystr[1..]); //"bcd"
println!("mystr :{:?}", &mystr[..]); // "abcd"
// &String
let my_str:String = "ABCD".to_string();
println!("my_str :{:?}", &my_str[1..2]); //"BC"
println!("my_str :{:?}", &my_str[1..]); //"BCD"
println!("my_str :{:?}", &my_str[..]); //"ABCD"
}
➜ main make
rustc main.rs
./main
mystr :"b"
mystr :"bcd"
mystr :"abcd"
my_str :"B"
my_str :"BCD"
my_str :"ABCD"
➜ main
2. 不能对 str、String 直接切割
fn main()
{
// &str
let mystr:&str = "abcd";
println!("mystr :{:?}", mystr[1..]); // =>error
// &String
let my_str:String = "ABCD".to_string();
println!("my_str :{:?}", my_str[1..]); // =>error
}
➜ main make
rustc main.rs
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> main.rs:5:3
|
5 | println!("mystr :{:?}", mystr[1..]); // =>error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: required by `std::fmt::ArgumentV1::new`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> main.rs:9:3
|
9 | println!("my_str :{:?}", my_str[1..]); // =>error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: required by `std::fmt::ArgumentV1::new`
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error: aborting due to 2 previous errors
make: *** [all] Error 101
➜ main
10. String.extend(&['a','b','c'])
fn main() {
let mut message = String::from("==> ");
message.extend(&['a', 'b', 'c']);
println!("message = {:?}", message);
}
➜ main make
rustc main.rs
./main
message = "==> abc"
➜ main
4、数组
1. 不可变数组
fn main() {
let arr1 = [0, 1, 2, 3, 4];
println!("{:?}", arr1);
let arr2 = &arr1[1..3];
println!("{:?}", arr2);
}
➜ main make
rustc main.rs
./main
[0, 1, 2, 3, 4]
[1, 2]
➜ main
2. 可变数组
fn main() {
// [i32; 3] => [数组元素类型 : 数组长度]
// [0; 3] => 使用0填充3个位置
let mut array : [i32; 3] = [0; 3];
for x in &array {
print!("{} ", x);
}
println!("");
// 修改数组[i]
array[1] = 1;
array[2] = 2;
//
for x in &array {
print!("{} ", x);
}
println!("");
}
➜ main make
rustc main.rs
./main
0 0 0
0 1 2
➜ main
3. Vec
1. 不可变 Vec
fn main() {
//创建空Vec
let v: Vec = Vec::new();
//使用宏创建空Vec
let v: Vec = vec![];
//创建包含5个元素的Vec
let v = vec![1, 2, 3, 4, 5];
//创建十个零
let v = vec![0; 10];
}
2. 可变 Vec
fn main() {
//创建可变的Vec,并压入元素3
let mut v = vec![1, 2];
v.push(3);
//创建拥有两个元素的Vec,并弹出一个元素
let mut v = vec![1, 2];
let two = v.pop();
//创建包含三个元素的可变Vec,并索引一个值和修改一个值
let mut v = vec![1, 2, 3];
let three = v[2];
v[1] = v[1] + 5;
}
3. 珂理化初始化方式
fn main()
{
let x: Vec = {
let mut temp_vec = Vec::new();
temp_vec.push(1);
temp_vec.push(2);
temp_vec.push(3);
temp_vec
};
println!("{:?}", x)
}
➜ main make
rustc main.rs
./main
[1, 2, 3]
➜ main
5、元祖
1. 构建元祖
fn main() {
// 不可变绑定形式的元祖1
// arg1 => int 32 值
// arg2 => &string 内存地址
let tuple1: (i32, &str) = (50, "hello");
println!("tuple1 = {:?}", tuple1);
// 不可变绑定形式的元祖2
let age = 99;
let name : &str = "hello";
let tuple2: (i32, &str) = (age, name);
println!("tuple2 = {:?}", tuple2);
}
➜ main make
rustc main.rs
./main
tuple1 = (50, "hello")
tuple2 = (99, "hello")
➜ main
2. 元祖内元素的可选绑定与不可选绑定
fn main() {
// 元祖
// => a 不可变绑定
// => b 可变绑定
let (a, mut b): (bool,bool) = (true, false);
println!("a = {:?}, b = {:?}", a, b);
// a 不可变绑定
// a = false; // error: cannot assign twice to immutable variable `a`
// b 可变绑定
b = true;
// 数据类型比较
assert_eq!(a, b);
}
➜ main make
rustc main.rs
./main
a = true, b = false
➜ main
3. 绑定其他元祖内的元素
fn main() {
// 不可变绑定形式的元祖1
// arg1 => int 32 值
// arg2 => &string 内存地址
let tuple: (i32, &str) = (50, "hello");
println!("tuple = {:?}", tuple);
// 绑定上面定义的元祖的arg1
let (arg1_1, _) = tuple;
let arg1_2 = tuple.0;
println!("arg1_1 = {:?}", arg1_1);
println!("arg1_2 = {:?}", arg1_2);
// 绑定上面定义的元祖的arg2
let arg2 = tuple.1;
println!("arg2 = {:?}", arg2);
}
➜ main make
rustc main.rs
./main
tuple = (50, "hello")
arg1_1 = 50
arg1_2 = 50
arg2 = "hello"
➜ main
6、指针
1. [内存地址] as *const T
1. C语言中的 const T* const p;
指针变量的值不能改变
fn main() {
let x = 5;
//【不可变绑定】对变量取地址
let ptr = &x as *const i32;
println!("ptr = {:p}", ptr);
// unsafe{...} 对指针进行【解地址】读取内存空间的数据
let val = unsafe { *ptr };
println!("val = {:?}", val);
}
➜ main make
rustc main.rs
./main
ptr = 0x7fff5135971c
val = 5
➜ main
2. C语言中的 T* const p;
指针变量指向内存的值不能改变
fn main() {
let x = 5;
let y = 6;
//【可变绑定】对变量取地址
let mut ptr = &x as *const i32;
println!("ptr = {:p}", ptr);
// 解地址读取内存空间的数据
let val = unsafe { *ptr };
println!("*ptr = {:?}", val);
// 重新指向其他变量标记的内存地址
ptr = &y;
println!("*ptr = {:?}", unsafe{*ptr});
}
➜ main make
rustc main.rs
./main
ptr = 0x7fff5ac9b6c8
*ptr = 5
*ptr = 6
➜ main
2. [内存地址] as *mut T
1. const指针转换为mut指针
fn main() {
// 栈帧上局部变量
let x = 5;
// *const T 类型指针
let ptr1 = &x as *const i32;
// let ptr1 : *const i32 = &x as *const i32; // 同上
println!("*ptr1 = {:?}", unsafe {*ptr1});
// *const T => *mut T
let ptr2 = ptr1 as *mut i32;
// 修改 *mut T 类型指针变量指向的内存空间中的数据
unsafe {*ptr2 = 6};
println!("*ptr2 = {:?}", unsafe {*ptr2});
}
➜ main make
rustc main.rs
./main
*ptr1 = 5
*ptr2 = 6
➜ main
2. 直接定义 mut 类型变量与指针变量
fn main() {
// 直接定义mut可变绑定类型变量
let mut x = 2;
// 获取可变绑定类型变量的内存地址
let ptr = &mut x as *mut i32;
// 读取地址空间中的数据
println!("*ptr = {:?}", unsafe {*ptr});
// 修改地址空间中的数据
unsafe {*ptr = 3};
println!("*ptr = {:?}", unsafe {*ptr});
}
➜ main make
rustc main.rs
./main
*ptr = 2
*ptr = 3
➜ main
7、结构体
1. 定义结构体与使用
struct Point {
x: f64,
y: f64,
}
fn main() {
// 创建struct实例
let point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
// 绑定获取struct实例成员的值
let Point { x: my_x, y: my_y } = point;
println!("my_x = {}, my_y = {}", my_x, my_y);
}
➜ main make
rustc main.rs
./main
point coordinates: (0.3, 0.4)
my_x = 0.3, my_y = 0.4
➜ main
2. 不能在struct内定义mut类型成员
struct Point {
mut x: i32, // error
y: i32,
}
3. 成员具有默认值
#[derive(Default)] // 成员初始化默认值
#[derive(Debug)] // println!("{:?}", struct实例);
struct Point3d {
x: i32,
y: i32,
z: i32,
}
fn main()
{
// 创建struct实例,并给成员默认初始化
let origin = Point3d::default();
println!("{:?}", origin);
// 赋值实例的成员y
let point = Point3d { y: 1, ..origin };
println!("{:?}", point);
// 获取struct实例的成员x、成员y的值
let Point3d { x: x0, y: y0, .. } = point;
println!("{} - {}", x0, y0);
}
➜ main make
rustc main.rs
./main
Point3d { x: 0, y: 0, z: 0 }
Point3d { x: 0, y: 1, z: 0 }
0 - 1
➜ main
4. struct之间的包含
#[derive(Debug)]
struct Point {
x: f64,
y: f64,
}
#[allow(dead_code)] //包含其他的struct作为成员
#[derive(Debug)]
struct Rectangle {
p1: Point,
p2: Point,
}
fn main() {
// 创建Point实例
let point: Point = Point { x: 0.3, y: 0.4 };
println!("point coordinates: ({}, {})", point.x, point.y);
// 创建Rectangle实例
let rectangle = Rectangle {
p1: Point { x: point.x + 0.5, y: point.y + 0.5},
p2: point,
};
println!("{:?}", rectangle);
}
➜ main make
rustc main.rs
./main
point coordinates: (0.3, 0.4)
Rectangle { p1: Point { x: 0.8, y: 0.9 }, p2: Point { x: 0.3, y: 0.4 } }
➜ main
5. 元祖类型的struct
struct Pair(i32, f64);
fn main() {
// Instantiate a tuple struct
let pair = Pair(1, 0.1);
// Destructure a tuple struct
let Pair(a, b) = pair;
println!("a = {:?}, b = {:?}", a, b);
}
➜ main make
rustc main.rs
./main
a = 1, b = 0.1
➜ main
6. Nil struct
#[derive(Debug)]
struct Nil;
fn main() {
let _nil = Nil;
println!("{:?}", _nil);
}
➜ main make
rustc main.rs
./main
Nil
➜ main
7. 结构体成员可变
use std::cell::Cell;
#[derive(Debug)]
struct Point {
x: i32,
y: Cell,
}
fn main()
{
let point = Point { x: 5, y: Cell::new(6) };
println!("{:?}", point);
point.y.set(7);
println!("{:?}", point);
}
➜ main make
rustc main.rs
./main
Point { x: 5, y: Cell { value: 6 } }
Point { x: 5, y: Cell { value: 7 } }
➜ main
8. mod内定义struct
1. mod内定义struct必须使用pub修饰,才能被外部使用
mod graph {
#[derive(Default)]
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
}
fn main()
{
let point = graph::Point::default(); // error
}
➜ main make
rustc main.rs
error[E0603]: struct `Point` is private
--> main.rs:13:15
|
13 | let point = graph::Point::default(); // error
| ^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
make: *** [all] Error 101
➜ main
2. mod内的struct成员也必须使用pub修饰
mod graph {
#[derive(Default)]
#[derive(Debug)]
pub struct Point {
pub x: i32,
y: i32,
}
}
fn main()
{
let point = graph::Point::default();
println!("{:?}", point);
println!("{:?}", point.x);
println!("{:?}", point.y); // error: field `y` of struct `graph::Point` is private
}
➜ main make
rustc main.rs
error[E0616]: field `y` of struct `graph::Point` is private
--> main.rs:15:20
|
15 | println!("{:?}", point.y); // error: field `y` of struct `graph::Point` is private
| ^^^^^^^
error: aborting due to previous error
make: *** [all] Error 101
➜ main
去掉访问point.y即可正常执行
➜ main make
rustc main.rs
./main
Point { x: 0, y: 0 }
0
➜ main
3. mod内定义操作struct实例的外部调用函数
mod graph {
use std::cell::Cell;
#[derive(Default)]
#[derive(Debug)]
pub struct Point {
x: Cell, // mod 私有成员
y: Cell, // mod 私有成员
}
pub fn init(p: Point, x: i32, y: i32) {
p.x.set(x);
p.y.set(y);
println!("{:?}", p);
}
}
fn main()
{
let point = graph::Point::default();
graph::init(point, 99, 100);
}
➜ main make
rustc main.rs
./main
Point { x: Cell { value: 99 }, y: Cell { value: 100 } }
➜ main
9. 枚举 => enum内定义struct
#[derive(Debug)]
enum Message {
Quit,
ChangeColor(i32, i32, i32), // 元祖类型结构体
Move { x: i32, y: i32 }, // 字段类型结构体
Write(String), // 元祖类型结构体
}
fn main()
{
let a: Message = Message::Quit;
let b: Message = Message::ChangeColor(1,2,3);
let c: Message = Message::Move { x: 3, y: 4 };
let d: Message = Message::Write(String::from("hello"));
println!("{:?}", a);
println!("{:?}", b);
println!("{:?}", c);
println!("{:?}", d);
}
➜ main make
rustc main.rs
./main
Quit
ChangeColor(1, 2, 3)
Move { x: 3, y: 4 }
Write("hello")
➜ main
9、type 类型别名
fn main() {
type NanoSecond = u64;
type Point = (u8, u8);
let x : NanoSecond = 19999;
let y : Point = (1,2);
println!("x = {:?}", x);
println!("y = {:?}", y);
}
➜ main make
rustc main.rs
./main
x = 19999
y = (1, 2)
➜ main
10、常量 与 静态量
1. 常量
const N: i32 = 5;
2. 静态全局变量
static N: i32 = 5; // 注意:必须标注一个静态的类型
3. 静态变量可变性
static mut N: i32 = 5;
4. 静态全局变量的多线程同步
static mut N: i32 = 5;
// 读写包裹在unsafe{}块中执行
unsafe {
N += 1;
println!("N: {}", N);
}
10、编译属性
1.【启用/关闭】编译属性
1. 启用
#[属性名(参数)]
2. 关闭
#![属性名(参数)]
在[前面加上一个!符号。
2. 开启 debug
#[derive(Debug)]
3. 开启 inline 内联
#[inline(always)]
4. 使用自定义编译属性
#[cfg(test)]
5. 使用系统预定义编译属性
#[cfg(target_os = "macos")]