diff --git a/src/basic/converse.md b/src/basic/converse.md index cc56abc5..6ff7a47c 100644 --- a/src/basic/converse.md +++ b/src/basic/converse.md @@ -283,3 +283,38 @@ impl Clone for Container { 你以为你之前凝视的是深渊吗?不,你凝视的只是深渊的大门。 `mem::transmute_copy` 才是真正的深渊,它比之前的还要更加危险和不安全。它从 `T` 类型中拷贝出 `U` 类型所需的字节数,然后转换成 `U`。 `mem::transmute` 尚有大小检查,能保证两个数据的内存大小一致,现在这哥们干脆连这个也丢了,只不过 `U` 的尺寸若是比 `T` 大,会是一个未定义行为。 当然,你也可以通过原生指针转换和 `unions` (todo!)获得所有的这些功能,但是你将无法获得任何编译提示或者检查。原生指针转换和 `unions` 也不是魔法,无法逃避上面说的规则。 + +`transmute` 虽然危险,但作为一本工具书,知识当然要全面,下面列举两个有用的 `transmute` 应用场景 :)。 + +- 将原生指针变成函数指针: + +```rust +fn foo() -> i32 { + 0 +} + +let pointer = foo as *const (); +let function = unsafe { + // 将原生指针转换为函数指针 + std::mem::transmute::<*const (), fn() -> i32>(pointer) +}; +assert_eq!(function(), 0); +``` + +- 延长生命周期,或者缩短一个静态生命周期寿命: + +```rust +struct R<'a>(&'a i32); + +// 将 'b 生命周期延长至 'static 生命周期 +unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> { + std::mem::transmute::, R<'static>>(r) +} + +// 将 'static 生命周期缩短至 'c 生命周期 +unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>) -> &'b mut R<'c> { + std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r) +} +``` + +以上例子非常先进!但是是非常不安全的 Rust 行为! diff --git a/src/basic/result-error/panic.md b/src/basic/result-error/panic.md index 4aa1fc67..114e6591 100644 --- a/src/basic/result-error/panic.md +++ b/src/basic/result-error/panic.md @@ -172,7 +172,7 @@ let home: IpAddr = "127.0.0.1".parse().unwrap(); 当调用 `panic!` 宏时,它会 1. 格式化 `panic` 信息,然后使用该信息作为参数,调用 `std::panic::panic_any()` 函数 -2. `panic_any` 会检查应用是否使用了 `panic hook`,如果使用了,该 `hook` 函数就会被调用(`hook` 是一个钩子函数,是外部代码设置的,用于在 `panic` 触发时,执行外部代码所需的功能) +2. `panic_any` 会检查应用是否使用了 [`panic hook`](https://doc.rust-lang.org/std/panic/fn.set_hook.html),如果使用了,该 `hook` 函数就会被调用(`hook` 是一个钩子函数,是外部代码设置的,用于在 `panic` 触发时,执行外部代码所需的功能) 3. 当 `hook` 函数返回后,当前的线程就开始进行栈展开:从 `panic_any` 开始,如果寄存器或者栈因为某些原因信息错乱了,那很可能该展开会发生异常,最终线程会直接停止,展开也无法继续进行 4. 展开的过程是一帧一帧的去回溯整个栈,每个帧的数据都会随之被丢弃,但是在展开过程中,你可能会遇到被用户标记为 `catching` 的帧(通过 `std::panic::catch_unwind()` 函数标记),此时用户提供的 `catch` 函数会被调用,展开也随之停止:当然,如果 `catch` 选择在内部调用 `std::panic::resume_unwind()` 函数,则展开还会继续。 diff --git a/src/index-list.md b/src/index-list.md index 83ead863..91bcae23 100644 --- a/src/index-list.md +++ b/src/index-list.md @@ -83,9 +83,12 @@ ## F -| 名称 | 关键字 | 简介 | -| ---- | ------ | ------------- | -| F | KWF | FIntroduction | +| 名称 | 关键字 | 简介 | +| -------- | -------- | -------------------------- | +| [浮点数] | 数值类型 | `f32`
`f64`(默认类型) | +| F | KWF | FIntroduction | + +[浮点数]: https://course.rs/basic/base-type/numbers.html#浮点类型 [back](#head) @@ -192,9 +195,14 @@ ## S -| 名称 | 关键字 | 简介 | -| ---- | ------ | ------------- | -| S | KWS | SIntroduction | +| 名称 | 关键字 | 简介 | +| ------------ | -------- | ------------------------------------------------------------------------------------------------------ | +| [整数] | 数值类型 | 有符号整数,`i8`,`i16`,`i32`,`i64`,`i128`,`isize`
无符号整数,`u8`,`u16`,`u32`,`u64`,`u128`,`usize` | +| [整形字面量] | 进制书写 | 十进制 `98_222`
十六进制 `0xff`
八进制 `0o77`
二进制 `0b1111_0000`
字节(仅限于`u8`) `b'A'` | +| S | KWS | SIntroduction | + +[整数]: https://course.rs/basic/base-type/numbers.html#整数类型 +[整形字面量]: https://course.rs/basic/base-type/numbers.html#整数类型 [back](#head) @@ -232,9 +240,12 @@ ## X -| 名称 | 关键字 | 简介 | -| ---- | ------ | ------------- | -| X | KWX | XIntroduction | +| 名称 | 关键字 | 简介 | +| ------ | ------ | ---------------------------------------------------------------------------------- | +| [序列] | Range | 生成连续的数值
只允许用于数字或字符类型
`..` 右半开区间
`..=` 闭合区间 | +| X | KWX | XIntroduction | + +[序列]: https://course.rs/basic/base-type/numbers.html#序列range [back](#head)