Linux学习笔记2---Makefile

news2024/11/19 20:13:51

单个文件编译用gcc编译确实是挺方便的,但是多个文件需要编译一个个的编译就属实是麻烦了,而针对多文件编译也有快捷的办法,即Makefile脚本。要运行Makefile需要先安装make程序。

apt install make

1.什么是Makefile

        一个工程中的源文件不计其数,按期类型、功能、模块分别放在若干个文件中,MakeFile文件定义了一系列的规则来制定哪些文件需先要编译、哪些文案需要后编译、哪些文件需要重新编译、甚至于进行更加复杂的操作,因为Makefile文件就像是一个shell脚本一样,也可以执行操作系统的命令

        Makefile 带来的好处就是 自动化编译,一旦写好,只需要一个make命令,整个工程完全自动化编译,极大提高了软件开发效率,make是一个命令工具,是一个解释Makefile文件中指令的命令工具,一般来说,大多数的IDE都有这个命令,例如Delphi的make、Visual C++的nmaek、Linux下Gun的make。

2.Makefile文件命名规则

  • 文件命名:Makefile或者makefile
  • makefile规则
    • 一个Makefile文件中可以有一个或者多个命名规则
                目标… :  依赖 …
                命令(shell命令)
                 …  
    • 目标:最终要生成的文件
    • 依赖:生成目标所需要的文件或者目标
    • 命令:通过执行命令对依赖金慈宁宫操作从而生成目标(命令前必须tab缩进)
  • Makefile中的其他规则一般都是为第一条规则服务的

3.编写Makefile

1、创建Makefile文件

vim Makefile

2、编写Makefile程序

main: main.o input.o calcu.o
	gcc -o main main.o input.o calcu.o
main.o: main.c
	gcc -c main.c
input.o:input.c
	gcc -c input.c
calcu.o:calcu.c
	gcc -c calcu.c
clean:
	rm *.o
	rm main

        上述代码中所有行首需要空出来的地方一定要使用“TAB”键!不要使用空格键!!!!

3、编写main.c、input.c和calcu.c文件及头函数

//main.c
#include <stdio.h>
#include "input.h"
#include "calcu.h"

 int main(int argc, char *argv[])
{
      	int a, b, num;
	input_int(&a, &b);
	num = calcu(a, b);
	printf("%d + %d = %d\r\n", a, b, num);
}
// input.c
#include <stdio.h>
 #include "input.h"

 void input_int(int *a, int *b)
	 {
		  printf("input two num:");
		   scanf("%d %d", a, b);
		    printf("\r\n");
	 }
//input.h
#ifndef _INPUT_H
 #define _INPUT_H

 void input_int(int *a, int *b);
  #endif

 
//calcu.c
#include "calcu.h"
int calcu(int a, int b)
{
	 return (a + b);
	  }
//calcu.h
#ifndef _CALCU_H
 #define _CALCU_H

 int calcu(int a, int b);
  #endif

4、运行make命令编译程序

make

运行之后会生成calcu.o,input.o,main.o,main文件

5、运行main执行文件

./main

 

即可运行所编译的程序

6、清理命令

make clean

 如果程序没有更新,再次运行make命令是不会再次编译的,可以将生成的.o文件都删除之后再次运行make命令,而在Makefile文件中我们编写了清理.o文件的程序,因此可以直接调用make clean命令进行清除。

以上就是一个Makefile的简单运用。现在对这个Makefile文件进行讲解。

7、Makefile 的工作原理

  • 执行命令之前需先检查规则中的依赖是否存在
    • 如果存在,执行命令
    • 如果不存在,向下检查其他规则,检查有没有一个规则是用来生成这个依赖的,如果找到了则执行改规则中的命令
  • 检测更新
    • 如果依赖的时间比目标的时间晚,则需要重新生成目标
    • 如果依赖的时间比目标的时间早,目标不需要更新,对应规则中的目标不需要执行。

 

第一条规则:

main : main.o input.o calcu.o
     gcc -o main main.o input.o calcu.o

这条规则的目标是 main,main.o、input.o 和 calcu.o 是生成 main 的依赖文件,如果要更新
目标 main,就必须先更新它的所有依赖文件,如果依赖文件中的任何一个有更新,那么目标也
必须更新,“更新”就是执行一遍规则中的命令列表。
        命令列表中的每条命令必须以 TAB 键开始,不能使用空格!
make 命令会为 Makefile 中的每个以 TAB 开始的命令创建一个 Shell 进程去执行。

        首先更新第一条规则中的 main,第一条规则的目标成为默认目标,只要默认目标更新了那
么就认为 Makefile 的工作。在第一次编译的时候由于 main 还不存在,因此第一条规则会执行,
第一条规则依赖于文件 main.o、input.o 和 calcu.o 这个三个.o 文件,这三个.o 文件目前还都没
有,因此必须先更新这三个文件。make 会查找以这三个.o 文件为目标的规则并执行。以 main.o
为例,发现更新 main.o 的是第二条规则

main.o: main.c
        gcc -c main.c

因此会执行第二条规则,第二条规则里面的命令为“gcc
–c main.c”,这行命令很熟悉了吧,就是不链接编译 main.c,生成 main.o,其它两个.o 文件同理。
        最后一个规则目标是 clean,它没有依赖文件,因此会默认为依赖文件都是最新的,所以其对应的命令不会执行,当我们想要执行 clean 的话可以直接使用命令“make clean”,执行以后就会删
除当前目录下所有的.o 文件以及 main,因此 clean 的功能就是完成工程的清理。

总结一下 Make 的执行过程:
        1、make 命令会在当前目录下查找以 Makefile(makefile 其实也可以)命名的文件。
        2、当找到 Makefile 文件以后就会按照 Makefile 中定义的规则去编译生成最终的目标文件。
        3、当发现目标文件不存在,或者目标所依赖的文件比目标文件新(也就是最后修改时间比
目标文件晚)的话就会执行后面的命令来更新目标。
        这就是 make 的执行过程,make 工具就是在 Makefile 中一层一层的查找依赖关系,并执行
相应的命令。编译出最终的可执行文件。Makefile 的好处就是“自动化编译”,一旦写好了 Makefile
文件,以后只需要一个 make 命令即可完成整个工程的编译,极大的提高了开发效率。

        总结一下,Makefile 中规则用来描述在什么情况下使用什么命令来构建一个特定的文件,
这个文件就是规则的“目标”,为了生成这个“目标”而作为材料的其它文件称为“目标”的依
赖,规则的命令是用来创建或者更新目标的。
        除了 Makefile 的“终极目标”所在的规则以外,其它规则的顺序在 Makefile 中是没有意义
的,“终极目标”就是指在使用 make 命令的时候没有指定具体的目标时,make 默认的那个目
标,它是 Makefile 文件中第一个规则的目标,如果 Makefile 中的第一个规则有多个目标,那么
这些目标中的第一个目标就是 make 的“终极目标”。 

4. Makefile 变量

跟 C 语言一样 Makefile 也支持变量的,先看一下前面的例子:

 main: main.o input.o calcu.o
     gcc -o main main.o input.o calcu.o

        上述 Makefile 语句中,main.o input.o 和 calcue.o 这三个依赖文件,我们输入了两遍,我们
这个 Makefile 比较小,如果 Makefile 复杂的时候这种重复输入的工作就会非常费时间,而且非
常容易输错,为了解决这个问题,Makefile 加入了变量支持。不像 C 语言中的变量有 int、char
等各种类型,Makefile 中的变量都是字符串!类似 C 语言中的宏。使用变量将上面的代码修改,
修改以后如下所示:

                                       # 示例代码  Makefile 变量使用

#Makefile 变量的使用
objects = main.o input.o calcu.o
main: $(objects)
        gcc -o main $(objects) 

        第 1 行是注释,Makefile 中可以写注释,注释开头要用符号“#”,不能用 C 语言中的“//”或者“/**/”!第 2 行我们定义了一个变量 objects,并且给这个变量进行了赋值,其值为字符串“main.o input.o calcu.o”,第 3 和 4行使用到了变量 objects, Makefile 中变量的引用方法是“$(变量名)”,比如本例中的“$(objects)”就是使用变量 objects。我们在定义变量 objects 的时候使用“=”对其进行了赋值,Makefile变量的赋值符还有其它两个“:=”和“?=”,我们来看一下这三种赋值符的区别:

1、赋值符“=”

        使用“=”在给变量的赋值的时候,不一定要用已经定义好的值,也可以使用后面定义的值,比如如下代码: 

name = zzk
curname = $(name)
name =h2z20str

print:
    @echo curname: $(curname)

         上述代码,第 1 行定义了一个变量 name,变量值为“zzk”,第 2 行也定义了一个变量curname,curname的变量值引用了变量name,按照我们C写语言的经验此时curname的值就是“zzk”。第 3 行将变量 name 的值改为了“h2z20str”,第 5、6 行是输出变量 curname的值。在 Makefile 要输出一串字符的话使用“echo”,就和 C 语言中的“printf”一样,第 6 行中的“echo”前面加了个“@”符号,因为 Make 在执行的过程中会自动输出命令执行过程,在命令前面加上“@”的话就不会输出命令执行过程,大家可以测试一下不加“@”的效果。使用命令“make print”来执行上述代码:

        可以看到curname的值不是“zzk”,竟然是“h2z20str”,也就是变量“name”最后一次赋值的结果,这就是赋值符“=”的神奇之处!借助另外一个变量,可以将变量的真实值推到后面去定义。也就是变量的真实值取决于它所引用的变量的最后一次有效值。

2、赋值符“:=”

       修改上面代码的第 2 行,将其中的“=”改为“:=”,修改完成以后的代码如下:

name = zzk
curname := $(name)
name =h2z20str

print:
        @echo curname: $(curname)

 修改完成以后重新执行一下 Makefile,结果可以看到此时的 curname 是 zzk,不是 h2z20str 了。这是因为赋值符“:=”,不会使用后面定义的变量,只能使用前面已经定义好的,这就是“=”和“:=”两个的区别。

3、赋值符“?=”

“?=”是一个很有用的赋值符,比如下面这行代码:

curname ?= h2z20str

        上述代码的意思就是,如果变量 curname 前面没有被赋值,那么此变量就是“zuozhongkai”,如果前面已经赋过值了,那么就使用前面赋的值。 

4、变量追加“+=”

        Makefile 中的变量是字符串,有时候我们需要给前面已经定义好的变量添加一些字符串进去,此时就要使用到符号“+=”,比如如下所示代码:

objects = main.o inpiut.o
objects += calcu.o

一开始变量 objects 的值为“main.o input.o”,后面我们给他追加了一个“calcu.o”,因此变量 objects 变成了“main.o input.o calcu.o”,这个就是变量的追加。

5. Makefile 模式规则

main.o: main.c
    gcc -c main.c
input.o: input.c
    gcc -c input.c
calcu.o: calcu.c
    gcc -c calcu.c

        以上是将对应的.c 源文件编译为.o 文件,每一个 C 文件都要写一个对应的规则,如果工程中 C 文件很多的话显然不能这么做。为此,我们可以使用 Makefile 中的模式规则,通过模式规则我们就可以使用一条规则来将所有的.c 文件编译为对应的.o 文件。模式规则中,至少在规则的目标定定义中要包涵“%”,否则就是一般规则,目标中的“%”表示对文件名的匹配,“%”表示长度任意的非空字符串,比如“%.c”就是所有的以.c 结尾的文件,类似与通配符,a.%.c 就表示以 a.开头,以.c 结束的所有文件。当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值,使用方法如下:

%.o : %.c
    命令

因此上面的 Makefile 可以改为如下形式:

objects = main.o input.o calcu.o
main:$(objects)
        gcc -o main $(objects)
%.o: %.c
       #命令

clean:
        rm *.o
        rm main

上述命令行还未编写,因此还未能编译。以上的%.o代表了所有的.o文件,%.c即代表了所有的.c文件,但仅在规则行中有用,在命令行中将不起作用,因此将需要引用另外的方法——自动变量

6.Makefile 自动化变量

        上面讲的模式规则中,目标和依赖都是一系列的文件,每一次对模式规则进行解析的时候都会是不同的目标和依赖文件,而命令只有一行,如何通过一行命令来从不同的依赖文件中生成对应的目标?自动化变量就是完成这个功能的!所谓自动化变量就是这种变量会把模式中所定义的一系列的文件自动的挨个取出,直至所有的符合模式的文件都取完,自动化变量只应该出现在规则的命令中,常用的自动化变量如表:

自动化变量描述
$@规则中的目标集合,在模式规则中,如果有多个目标的话,“$@”表示匹配模式中定义的目标集合。
$%当目标是函数库的时候表示规则中的目标成员名,如果目标不是函数库文件,那么其值为空。
$<依赖文件集合中的第一个文件,如果依赖文件是以模式(即“%”)定义的,那么“$<”就是符合模式的一系列的文件集合。
$?所有比目标新的依赖目标集合,以空格分开。
$^所有依赖文件的集合,使用空格分开,如果在依赖文件中有多个重复的文件,“$^”会去除重复的依赖文件,值保留一份。
$+和“$^”类似,但是当依赖文件存在重复的话不会去除重复的依赖文件。
$*这个变量表示目标模式中"%"及其之前的部分,如果目标是 test/a.test.c,目标模式为 a.%.c,那么“$*”就是 test/a.test。

表中的 7 个自动化变量中,常用的三种:$@、$<和$^,我们使用自动化变量来完成 Makefile文件,最终的完整代码如下所示:

objects = main.o input.o calcu.o
main:$(objects)
        gcc -o main $(objects)

%.o: %.c
       gcc -c $<

clean:
        rm *.o
        rm main

        上述代码代码就是修改后的完成的 Makefile,可以看出相对精简了很多,核心就在于第 5、6 这两行,第 5 行使用了模式规则,第 6 行使用了自动化变量。

7.Makefile 伪目标

        Makefile 有一种特殊的目标——伪目标,一般的目标名都是要生成的文件,而伪目标不代表真正的目标名,在执行 make 命令的时候通过指定这个伪目标来执行其所在规则的定义的命令。
        使用伪目标主要是为了避免 Makefile 中定义的执行命令的目标和工作目录下的实际文件出现名字冲突,有时候我们需要编写一个规则用来执行一些命令,但是这个规则不是用来创建文件的,比如在前面的Makefile中有如下代码用来完成清理工程的功能:

clean:
    rm *.o
    rm main

        上述规则中并没有创建文件 clean 的命令,因此工作目录下永远都不会存在文件 clean,当我们输入“make clean”以后,后面的“rm *.o”和“rm main”总是会执行。可是如果我们“手贱”,在工作目录下创建一个名为“clean”的文件,那就不一样了,当执行“make clean”的时候,规则因为没有依赖文件,所以目标被认为是最新的,因此后面的 rm 命令也就不会执行,我们预先设想的清理工程的功能也就无法完成。为了避免这个问题,我们可以将 clean 声明为伪目标,声明方式如下:

.PHONY : clean

则Makefile文件可修改如下:

objects = main.o input.o calcu.o
main:$(objects)
        gcc -o main $(objects)

.PHONY : clean

%.o: %.c
       gcc -c $<

clean:
        rm *.o
        rm main

        上述代码第 5 行声明 clean 为伪目标,声明 clean 为伪目标以后不管当前目录下是否存在名为“clean”的文件,输入“make clean”的话规则后面的 rm 命令都会执行。

8. Makefile 条件判断

 在 C 语言中我们通过条件判断语句来根据不同的情况来执行不同的分支,Makefile 也支持条件判断,语法有两种如下:

<条件关键字>
        <条件为真时执行的语句>
endif

以及:

<条件关键字>
        <条件为真时执行的语句>
else
        <条件为假时执行的语句>
endif

        其中条件关键字有 4 个:ifeq、ifneq、ifdef 和 ifndef,这四个关键字其实分为两对、ifeq 与ifneq、ifdef 与 ifndef,先来看一下 ifeq 和 ifneq,ifeq 用来判断是否相等,ifneq 就是判断是否不相等,ifeq 用法如下:

ifeq (<参数 1>, <参数 2>)
ifeq ‘<参数 1 >’,‘ <参数 2>’
ifeq “<参数 1>”, “<参数 2>”
ifeq “<参数 1>”, ‘<参数 2>’
ifeq ‘<参数 1>’, “<参数 2>”

        上述用法中都是用来比较“参数 1”和“参数 2”是否相同,如果相同则为真,“参数 1”和“参数 2”可以为函数返回值。ifneq 的用法类似,只不过 ifneq 是用来了比较“参数 1”和“参数 2”是否不相等,如果不相等的话就为真。

        ifdef 和 ifndef 的用法如下:

ifdef <变量名>

如果“变量名”的值非空,那么表示表达式为真,否则表达式为假。“变量名”同样可以是一个函数的返回值。ifndef 用法类似,但是含义用户 ifdef 相反。

例:

first = g++
second = g++

all:
ifeq ($(first), $(second))
	echo `first == second`
else
	echo `first != second`
endif

 9. Makefile 函数使用

Makefile 支持函数,类似 C 语言一样,Makefile 中的函数是已经定义好的,我们直接使用,不支持我们自定义函数。make 所支持的函数不多,但是绝对够我们使用了,函数的用法如下:

$(函数名 参数集合) 

或者:

${函数名 参数集合}

可以看出,调用函数和调用普通变量一样,使用符号“$”来标识。参数集合是函数的多个
参数,参数之间以逗号“,”隔开,函数名和参数之间以“空格”分隔开,函数的调用以“$”开
头。接下来我们介绍几个常用的函数:

1、函数 subst

函数 subst 用来完成字符串替换,调用形式如下:

$(subst <from>,<to>,<text>)

此函数的功能是将字符串<text>中的<from>内容替换为<to>,函数返回被替换以后的字符串,比如如下示例:

$(subst h2z,H2Z,my name is h2z)

把字符串“my name is h2z”中的“h2z”替换为“H2Z”,替换完成以后的字符串为“my name is H2Z”
       

2、函数 patsubst 

          函数 patsubst 用来完成模式字符串替换,使用方法如下:

$(patsubst <pattern>,<replacement>,<text>)

此函数查找字符串<text>中的单词是否符合模式<pattern>,如果匹配就用<replacement>来替换掉,<pattern>可以使用通配符“%”,表示任意长度的字符串,函数返回值就是替换后的字符串。如果<replacement>中也包涵“%”,那么<replacement>中的“%”将是<pattern>中的那个“%”所代表的字符串,比如:

$(patsubst %.c,%.o,a.c b.c c.c)

将字符串“a.c b.c c.c”中的所有符合“%.c”的字符串,替换为“%.o”,替换完成以后的字符串为“a.o b.o c.o”。

3、函数 dir

函数 dir 用来获取目录,使用方法如下:

$(dir <names…>)

        此函数用来从文件名序列<names>中提取出目录部分,返回值是文件名序列<names>的目录部分,比如:

$(dir </src/a.c>)

        提取文件“/src/a.c”的目录部分,也就是“/src”。

4、函数 notdir

        函数 notdir 看名字就是知道去除文件中的目录部分,也就是提取文件名,用法如下:

$(notdir <names…>)

        此函数用与从文件名序列<names>中提取出文件名非目录部分,比如:

$(notdir </src/a.c>)

        提取文件“/src/a.c”中的非目录部分,也就是文件名“a.c”。

5、函数 foreach

        foreach 函数用来完成循环,用法如下:

$(foreach <var>, <list>,<text>)

        此函数的意思就是把参数<list>中的单词逐一取出来放到参数<var>中,然后再执行<text>所包含的表达式。每次<text>都会返回一个字符串,循环的过程中,<text>中所包含的每个字符串会以空格隔开,最后当整个循环结束时,<text>所返回的每个字符串所组成的整个字符串将会是函数foreach 函数的返回值。

6、函数 wildard

通配符“%”只能用在规则中,只有在规则中它才会展开,如果在变量定义和函数使用时,通配符不会自动展开,这个时候就要用到函数 wildcard,使用方法如下:

$(wildcard PATTERN…)

比如:

$(wildcard *.c)

上面的代码是用来获取当前目录下所有的.c 文件,类似“%”。

10.参考文献

Makefile 详解_make file-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1654947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何提高日语听力?日语学习日语培训柯桥小语种学校

每次一说起练日语听力&#xff0c;总离不开一个词&#xff0c;那就是“磨耳朵”。 可是&#xff0c;“磨耳朵”真的有用吗&#xff1f; 在讨论这个问题之前&#xff0c;我们需要先知道&#xff1a;什么是“磨耳朵”&#xff1f; 所谓的“磨耳朵”&#xff0c;其实就是让我们的耳…

【Ubuntu20.04安装java-8-openjdk】

1 下载 官网下载链接&#xff1a; https://www.oracle.com/java/technologies/downloads/#java8 下载 最后一行 jdk-8u411-linux-x64.tar.gz&#xff0c;并解压&#xff1a; tar -zxvf jdk-8u411-linux-x64.tar.gz2 环境配置 1、打开~/.bashrc文件 sudo gedit ~/.bashrc2、…

2024蓝桥杯CTF writeUP--packet

根据流量分析&#xff0c;我们可以知道129是攻击机&#xff0c;128被留了php后门&#xff0c;129通过get请求来获得数据 129请求ls Respons在这 里面有flag文件 这里请求打开flag文件&#xff0c;并以base64编码流传输回来 获得flag的base64的数据 然后解码 到手

知识点(慢慢更新..break,continue,return)

目录 一. break,continue,return用法和含义 1. break 2. continue 3. return 4. 总结 一. break,continue,return用法和含义 1. break break用于完全结束一个循环&#xff0c;跳出循环体&#xff0c;执行循环后面的语句。 使用场合主要是switch语句和循环结构。 ● 在循…

一键复制:基于vue实现的tab切换效果

需求&#xff1a;顶部栏有切换功能&#xff0c;内容区域随顶部切换而变化 目录 实现效果实现代码使用示例在线预览 实现效果 如下 实现代码 组件代码 MoTab.vue <template><div class"mo-tab"><divv-for"item in options"class"m…

Axure PR 10 下拉三级菜单设计图

在线预览地址&#xff1a;Untitled Document 程序员必备资源网站&#xff1a;天梦星服务平台 (tmxkj.top) 需要源码设计图联系我wx:19948765606,3块钱拿走

信息收集(详细)

文章目录 网站要素IP信息资产架构信息服务信息网站信息cms信息源码信息中间件信息 个人信息收集其它 渗透的第一步就是信息收集&#xff0c;通常信息收集的结果如何&#xff0c;会直接影响后续能否渗透成功。好的信息收集可以让攻击面更广&#xff0c;思路更加广。 本文对信息收…

Centos 中如何汉化man命令

刚学Linux&#xff0c;记不住命令和选项&#xff0c;很依赖里面的 man 查看命令&#xff0c;但因为着实看不懂&#xff0c;有没有什么办法把man查看命令的信息改成中文 在CentOS 7中&#xff0c;你可以通过安装man-pages-zh包来获取中文的man手册。以下是具体的步骤&#xff1a…

CCF-Csp算法能力认证, 202303-1重复局面(C++)含解析

前言 推荐书目&#xff0c;在这里推荐那一本《算法笔记》&#xff08;胡明&#xff09;&#xff0c;需要PDF的话&#xff0c;链接如下 「链接&#xff1a;https://pan.xunlei.com/s/VNvz4BUFYqnx8kJ4BI4v1ywPA1?pwd6vdq# 提取码&#xff1a;6vdq”复制这段内容后打开手机迅雷…

钟表——蓝桥杯十三届2022国赛大学B组真题

问题分析 这个问题的关键有两点&#xff1a;1.怎么计算时针&#xff0c;分针&#xff0c;秒针之间的夹角&#xff0c;2.时针&#xff0c;分针&#xff0c;秒针都是匀速运动的&#xff0c;并非跳跃性的。问题1很好解决看下面的代码就能明白&#xff0c;我们先考虑问题2&#xf…

第9章 负载均衡集群日常维护

一个设计良好的高可用负载均衡集群&#xff0c;交付使用以后并不能一劳永逸。欲使其高效、稳定、持续对外服务&#xff0c;日常维护必不可少。 对于高可用负载均衡集群来说&#xff0c;有两种类型的维护形式&#xff1a;常规性维护与突发性维护。突发性维护一般指故障处理&…

最大数字——蓝桥杯十三届2022国赛大学B组真题

问题分析 这道题属于贪心加回溯。所有操作如果能使得高位的数字变大必定优先用在高位&#xff0c;因为对高位的影响永远大于对低位的影响。然后我们再来分析一下&#xff0c;如何使用这两种操作&#xff1f;对于加操作&#xff0c;如果能使这一位的数字加到9则变成9&#xff0…

Docker与Harbor:构建企业级私有Docker镜像仓库

目录 引言 一、本地私有仓库 &#xff08;一&#xff09;基本概述 &#xff08;二&#xff09;搭建本地私有仓库 1.下载registry镜像 2.启动容器 3.上传本地镜像 4.客户端下载镜像 二、Harbor简介 &#xff08;一&#xff09;什么是 Harbor &#xff08;二&#xff…

IT外包能在企业上云时提供什么帮助?

在云计算不断发展的背景下&#xff0c;企业对IT部门的要求日益提高&#xff0c;越来越多的企业开始考虑将IT系统迁移到云上。因此&#xff0c;IT外包也成为企业成功上云的重要支持之一。IT外包在企业上云时具体能提供什么帮助&#xff1f;本文将对此进行详细阐述。 业务重心转移…

必应bing国内广告如何开户,怎么收费?

搜索引擎广告作为直接触达潜在客户的有效途径之一&#xff0c;日益受到企业的重视&#xff0c;必应Bing作为全球第二大搜索引擎&#xff0c;在中国市场同样拥有庞大的用户群体&#xff0c;为企业提供了不可忽视的广告投放平台。 一、必应bing国内广告开户流程 1、需求分析与咨…

C语言 循环语句 (3) for 循环语句

接下来 我们来看第三个 for语句 基本语句是 for关键字 然后小括号 括号中三个表达式 然后它对表达式2进行判断 如果表达式2条件成立 则走进循环体 执行完循环体 会回来执行表达式3 然后再返回来 继续对表达式2进行判断 如果表达式2 还是成立 这继续循环往复 直到表达式2的条件…

游戏理解入门:Rust+Bracket开发一个小游戏

1. Game loop 使用game loop可以使得游戏运行更加流畅和顺滑&#xff0c;它可以&#xff1a; 初始化窗口、图形和其他资源&#xff1b;每当屏幕刷新他都会运行(通常是每秒30,60 )&#xff1b;每次通过循环&#xff0c;他都会调用游戏的tick()函数。 大致的原理流程如下&…

那个在买珠宝的年轻人

金价搭上过山车&#xff0c;今年以来价格一路飙涨。 珍珠身价同步飙升&#xff0c;晋级珠宝圈“新宠”。 文玩圈“减龄”&#xff0c;盘珠串不再只是“老头乐”。 月薪3000的年轻人&#xff0c;悄悄实现“宝石”自由。 黄金珠宝走俏&#xff0c;这届年轻人到底有着怎样的珠宝…

揭秘文件加密利器:24年度最值得信赖的5大加密软件评测

数据安全与隐私保护已成为我们每个人都必须面对的重要问题。 文件加密软件作为保障数据安全的关键工具&#xff0c;其重要性不言而喻。 在众多的加密软件中&#xff0c;哪些软件能够在保障数据安全的同时&#xff0c;又具备良好的易用性和稳定性呢&#xff1f; 本文将为您揭秘…

快过VS Code,10天暴增20k star,高性能多人协作IDE横空出世

道歉 其实不意味着道歉的人错了 而是他认为这段关系 比自己的尊严更重要 失败了 不是说你有多差 而是说 你需要更努力了 写代码最重要的一个选择就是选哪个IDE了&#xff0c;目前主流的选择是vscode和IDEA了。 但是vscode虽然轻量&#xff0c;但是对于大型的项目仍然显得…