【rCore OS 开源操作系统】Rust 宏

embedded/2024/10/25 6:38:38/

前置知识点

各种宏

  1. 宏定义:

使用 macro_rules! 关键词来定义宏,这是一种模式匹配式的宏定义方式。
自 Rust 1.26 版本开始,可以使用 proc_macro 属性宏来定义过程宏(如 derive 宏)。

  1. 宏的使用:

宏可以通过定义好的宏名来调用,宏调用时传入的参数会被宏定义中的模式匹配所捕获,并根据定义的规则生成相应的代码。

  1. 卫生宏(hygiene):

Rust 的宏支持卫生性,这意味着宏调用时的上下文信息会被保留下来,以避免命名冲突等问题。

  1. 模式匹配:

Rust 的宏支持模式匹配,这使得宏可以根据传入的不同参数生成不同的代码。

  1. 过程宏(procedural macros):

Rust 支持三种类型的过程宏:derive 宏、属性宏(attribute-like macros)和函数宏(function-like macros)。

  1. derive 宏允许用户为自定义类型添加默认的行为。
  2. 属性宏和函数宏允许用户定义更加复杂的代码生成逻辑。
  3. 宏的可见性和导入:
    宏可以通过 pub use 语句来导入到其他模块中。
    在 Rust 2018 版本之前,需要使用 #[macro_use] 来导入宏。但在 Rust 2018 版本之后,可以直接通过 use 语句来导入宏。

和函数的区别

在Rust中,宏定义(macros)和函数(functions)有以下区别:

  1. 语法:宏定义采用 macro_rules! 关键字进行定义,而函数使用 fn 关键字进行定义。

  2. 调用方式:宏定义使用 ! 运算符来调用,而函数使用圆括号 () 运算符来调用。

  3. 参数传递:宏定义可以接受任意数量的参数,并且可以使用模式匹配来匹配传递的参数,而函数需要明确指定参数的数量和类型。

  4. 代码生成:宏定义在编译期间进行代码生成,将宏展开为实际的代码,而函数在运行时执行。

  5. 功能扩展:宏定义可以执行复杂的代码转换和代码生成,可以在编译期间进行元编程,而函数只能执行预定义的操作。

总的来说,宏定义在编译期间进行代码生成和转换,具有更高的灵活性和功能扩展性,但也更加复杂和难以理解。函数则是在运行时执行,更加简单和直观。在选择宏定义和函数之间,需要根据具体的需求和场景来决定。

练习题

macros1

题目

考点:注意宏需要用!来定义。

rust">// macros1.rs
//
// Execute `rustlings hint macros1` or use the `hint` watch subcommand for a
// hint.// I AM NOT DONEmacro_rules! my_macro {() => {println!("Check out my macro!");};
}fn main() {my_macro();
}
题解
rust">macro_rules! my_macro {() => {println!("Check out my macro!");};
}fn main() {my_macro!();
}

macros2

题目

在宏的定义中使用了

rust">// macros3.rs
//
// Make me compile, without taking the macro out of the module!
//
// Execute `rustlings hint macros3` or use the `hint` watch subcommand for a
// hint.// I AM NOT DONEmod macros {macro_rules! my_macro {() => {println!("Check out my macro!");};}
}fn main() {my_macro!();
}
题解

在 Rust 2018 之前,对于不在同一个直接 mod 下的 macro,都需要加 #[macro_use] 后才能使用。

rust">#[macro_use]
mod macros {macro_rules! my_macro {() => {println!("Check out my macro!");};}
}fn main() {my_macro!();
}

marcros3

题目
rust">// macros4.rs
//
// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a
// hint.// I AM NOT DONE#[rustfmt::skip]
macro_rules! my_macro {() => {println!("Check out my macro!");}($val:expr) => {println!("Look at this other macro: {}", $val);}
}fn main() {my_macro!();my_macro!(7777);
}
题解

其实就是考察宏可以重载:

rust">// macros4.rs
//
// Execute `rustlings hint macros4` or use the `hint` watch subcommand for a
// hint.#[rustfmt::skip]
macro_rules! my_macro {() => {println!("Check out my macro!");};($val:expr) => {println!("Look at this other macro: {}", $val);}
}fn main() {// 类似于一种重载my_macro!();my_macro!(7777);
}

http://www.ppmy.cn/embedded/132267.html

相关文章

uniapp:uni.createSelectorQuery函数结合vue的watch函数使用实例

提醒 本文实例是使用uniapp进行开发演示的。 一、需求场景 在开发详情页面时,不同产品描述文案不同,有的文案比较长,需求上要求描述文案最多展示4行文案,少于4行文案,全部显示,此UI高度自动适配&#xff0c…

网络爬虫-Python网络爬虫和C#网络爬虫

爬虫是一种从互联网抓取数据信息的自动化程序,通过 HTTP 协议向网站发送请求,获取网页内容,并通过分析网页内容来抓取和存储网页数据。爬虫可以在抓取过程中进行各种异常处理、错误重试等操作,确保爬取持续高效地运行 1、Python网…

平安养老险深圳分公司:创新养老服务,深入践行金融为民

党的二十届三中全会《决定》提出:“积极发展科技金融、绿色金融、普惠金融、养老金融、数字金融,加强对重大战略、重点领域、薄弱环节的优质金融服务。” 为经济社会发展提供高质量服务,更好满足人民日益增长的美好生活需要,金融…

ubuntu下快捷键启动程序

背景:公司自开发的软件,经常需要启动,每次去找目录启动很麻烦,所以想快捷启动 方法1: 通过编辑.baserc启动 例如启动程序是toolA, 放在/home/user/software/目录下,那么在~/.baserc里面加入一行代码 al…

Linux的例行性工作1

[rootserver ~]# vim test2.sh //编辑脚本 1、每分钟执行命令 [rootserver ~]# crontab -e [rootserver ~]# crontab -l* * * * * sh /root/test2.sh[rootserver ~]# ls anaconda-ks.cfg cro.txt dead.letter test2.sh testcrondtab.sh [rootserver ~]# cat cro.txt…

7、基于爬虫+Flask+Echarts+MySQL的网易云评论可视化大屏

基于爬虫FlaskEchartsMySQL的网易云评论可视化大屏 1、前言2、实现2.1 挑选想要采集的歌曲评论2.2 构建爬虫2.2.1 采集歌曲评论2.2.2 清洗数据入库 2.3 搭建flask框架2.4 数据传值2.5 完整代码&数据集获取 1、前言 本项目是基于requests爬虫flaskecharts搭建的网易云评论的…

Pandas 文件读取与保存指南:高效处理 CSV、Excel 等多种格式数据

Pandas 文件读取与保存指南:高效处理 CSV、Excel 等多种格式数据 本文详细介绍了如何使用 Pandas 的 IO 工具从各种常见文件格式(如 CSV、Excel、HTML、TXT 等)中读取和保存数据。通过 Pandas,用户可以轻松读取和修改数据&#x…

Java-线程池技术

一、线程池简介 线程池是一种池化的思想,是将一些共同资源放到池中进行管理和使用,从而避免大量的创建销毁带来的资源浪费等问题,线程池主要优点体现在: 降低资源消耗:普通线程创建执行完任务之后即被销毁&#xff0…