2023学习日志

2023-07-10 21:52:29 浏览数 (1)

makefile

使用变量

变量基础

makefile中的变量在声明时需要设置初始值,使用时需要在变量名前加"$" ,可以通过使用括号()或大括号{}包围变量名

示例:

代码语言:text复制
test = c
pro.o: pro.$(test)
    cc -c pro.$(test)

变量展开

不同于编程语言中变量的概念,Makefile中的变量更类似于c/c 中的概念,本质上是将变量的值替换到使用变量的地方

变量的嵌套

  • Makefile支持将变量的值赋给变量

但为了防止变量的递归定义,可以使用":="操作符,使用":="操作符的变量, 将其他变量赋值给该变量时只能使用前面已经声明的变量。而"="操作符支持在使用变量进行赋值时,可以使用在该赋值语句之后声明的变量

  • 也可在使用变量时进行嵌套操作

示例:

代码语言:text复制
# 将变量赋值给变量 使用=操作符
# 可以使用在该语句之前或之后定义的变量
test_1 = $(test_3)
test_3 = $(test_4)
test_4 = c
# 将变量赋值给变量 使用:=操作符
# 仅能使用在该语句之前声明的变量
test_1 = c
test_3 := $(test_1) 
# 使用嵌套变量
aaa = c
test = $($(aaa))

追加变量值

可以使用" ="操作符为变量追加值

如果变量未被定义,则" ="自动转变为"=",若变量已被定义,则会继承前次操作的赋值符

示例:

代码语言:text复制
# 变量未被定义,自动转换为"="
test  = a
# 变量test未声明过,因此 等价于 test = a

# 前次操作使用"="赋值,继承"="
test = k
test  = $(a)
a = cc
# 变量test已声明过,因此,等价于 test = $(test) $(a) 可以使用之后声明的变量

# 前次操作使用":="赋值,继承":="
a = k
b = c
test := $(a)
test  = $(b)
# 变量test已声明过,因此等价于 test := $(test) $(b) 只能使用之前声明的变量 

override指令

可以重新设置make命令行设置的变量值,在define指令前,同样可以使用override指令

语法如下:

代码语言:text复制
override <variable>; = <value>;
override <variable>; := <value>;
override <variable>;  = <value>;

多行变量

可以通过define关键字设置变量,此时可以有换行,与命令包类似,值得注意的是,define中的命令要以[tab]开头,才能被识别为命令

示例:

代码语言:text复制
# 其中命令未以[tab]开头,所以不会被识别命令
define two-lines
echo foo
echo $(bar)
endef

环境变量

make运行时可以获取到系统环境变量,也可以在make命令行中指定变量的值,或在Makefile中定义该变量,覆盖系统环境变量的值。

当make嵌套调用时,上层定义的变量会以环境变量的形式传递到下层make中。

默认情况下,只有命令行中的变量会被传递,但Makefile中以export关键字声明的变量可以传递给下层make)

目标变量

可以为某个目标设置局部变量,称为目标变量

目标变量可以和全局变量重名,作用范围为当前规则及其连带规则中,不会影响规则链之外全局变量的值

语法如下:

代码语言:text复制
<target ...> : <variable-assignment>;
<target ...> : override <variable-assignment>;

模式变量

为匹配某一模式目标定义目标变量

语法如下:

代码语言:text复制
<pattern ...>; : <variable-assignment>;
<pattern ...>; : override <variable-assignment>;

示例:

代码语言:text复制
%.o : CFLAGS = -0

rust

迭代器

惰性的迭代器

rust中的迭代器惰性的,即在调用迭代器之前,不会有任何作用。

for循环与迭代器

for循环的底层隐式地使用了迭代器

迭代器的作用

任何语言中迭代器的作用都是类似的:

  • 实现数据与抽象的分离
  • 提供统一、可靠的遍历数据序列(sequence)的方式
  • 无法对迭代器进行插入删除操作,限制使用者对数据的操作权限

Iterator trait 与 next方法

所有的迭代器都实现了定义于标准库Iterator trait

定义如下:

代码语言:scss复制
pub trait Iterator {
    tyoe Item;
    fn next(&mut self) -> Option<Self::Item>
    //忽略了各种方法的默认实现
}

next方法Iterator trait实现者必须实现的唯一方法,next方法一次返回迭代器中的一项,封装在Some中,而迭代器结束时,将返回None

消费适配器与迭代适配器

消费适配器

消费适配器即在Iterator trait 定义中调用了迭代器next方法的方法,如标准库实现的sum方法

迭代适配器

  • 迭代适配器Iterator trait定义中能够对迭代器进行类型转换,返回另一个类型的迭代器的方法,如map方法
  • 大部分迭代器适配器都能够接受闭包作为参数,且该闭包能够捕获周围环境

迭代器与性能

与使用封装好了的容器而非底层数组的原因类似,迭代器能够提供更高层级的抽象,且性能与底层实现几乎一致:零开销零成本抽象

0 人点赞