【Linux详解】——gcc/g++/gdb/git的使用

news/2024/5/8 19:32:05/文章来源:https://blog.csdn.net/HinsCoder/article/details/127585010

📖 前言:本期将学习gcc/g++/gdb/git的使用


目录

  • 🕒 1. 程序的翻译过程
  • 🕒 2. 理解选项的含义
  • 🕒 3. 动态链接和静态链接
  • 🕒 4. Linux项目自动化构建工具-make/Makefile
    • 🕘 4.1 背景
    • 🕘 4.2 使用
  • 🕒 5. Linux的第一个小程序-进度条
    • 🕘 5.1 缓冲区概念
    • 🕘 5.2 回车换行概念
    • 🕘 5.3 fflush(stdout)
    • 🕘 5.4 倒计时实现
    • 🕘 5.5 进度条实现
  • 🕒 6. git的使用
  • 🕒 7. gdb(调试工具)的使用

🕒 1. 程序的翻译过程

  1. 预处理(头文件展开,去注释,宏替换,条件编译)
  2. 编译:把C变成汇编语言
  3. 汇编:把汇编变成二进制(不是可执行,二进制目标文件不能被执行)
  4. 链接:把你下的代码和C标准库中的代码合起来

🕒 2. 理解选项的含义

首先输入一段测试代码

#include<stdio.h>
#define M 666
int main()
{            // 测试注释printf("Hello 1\n");// printf("Hello 1\n");                                                // printf("Hello 2\n");// printf("Hello 3\n");// printf("Hello 4\n")   printf("Hello 5\n");   //测试条件编译
#ifdef SHOW             printf("Hello show!\n");
#else             printf("Hello default\n");
#endif                      // 测试宏                 printf("宏:%d\n", M);return 0;
}            

直接执行会一步到位输出结果

[hins@VM-12-13-centos testLinux]$ vim test.c
[hins@VM-12-13-centos testLinux]$ gcc test.c
[hins@VM-12-13-centos testLinux]$ ll
total 16
-rwxrwxr-x 1 hins hins 8408 Oct 29 12:04 a.out
-rw-rw-r-- 1 hins hins  414 Oct 29 12:03 test.c
[hins@VM-12-13-centos testLinux]$ ./a.out
Hello 1
Hello 5
Hello default
宏:666

但是我们要理解上面四个过程,就要划分成四条指令依次执行上述的四步翻译过程,在此期间理解选项的含义。

  1. 预处理: gcc -E test.c -o test.i,其中-E表示从现在开始,进行程序的翻译,当将预处理做完,就停下来。-o指明形成的临时文件名称
    在这里插入图片描述
  2. 编译: gcc -S test.i -o test.s,把C语言转成汇编语言
  3. 汇编: gcc -c test.s -o test.o,把汇编语言变成可重定向目标二进制文件。od test.o:打开二进制文件。
  4. 链接: gcc test.o -o test.out,形成可执行二进制程序(库+你的代码)

🕒 3. 动态链接和静态链接

首先我们要清楚,我们自己写的代码和库是两码事。C标准库是别人给我们准备好的,让我们直接使用的。我们所有使用库中函数的代码(如printf()),其中我们自己只写了该函数的调用,没有对应的实现!只有当链接的时候,对应的实现才和我们的代码关联起来!

那么这就引入了链接,链接的本质:就是我们调用库函数的时候和标准库如何关联的问题。这种关联就包括动态和静态。
在这里插入图片描述

  • 动态链接: 受库升级或者被删除的影响,形成的可执行程序小,节省资源。
  • 静态链接: 不受库升级或者被删除的影响,形成的可执行程序较大! – 网络,磁盘,内存

在Linux下库的命名:

  • 动态库:lib XXX.so 例:libc.so.6就是c标准库
  • 静态库:lib XXX.a

在Windows下:

  • 动态库:.dll
  • 静态库:.lib

当我们执行查看c标准库的时候,就可以看到具体的信息,并发现此标准库默认是.so结尾的动态库。

[hins@VM-12-13-centos testLinux]$ ls /lib64/libc.so.6 -l
lrwxrwxrwx 1 root root 12 Jul 25 16:58 /lib64/libc.so.6 -> libc-2.17.so
[hins@VM-12-13-centos testLinux]$ ls /lib64/libc-2.17.so -al
-rwxr-xr-x 1 root root 2156592 May 19 00:18 /lib64/libc-2.17.so

对于动态库和静态库来说,动态库是系统自带的,即系统安装完毕就可以使用,而静态库则一般需要我们自己安装,这也说明了静态库并不是直接拷贝动态库的内容。因此我们需要手动安装一下静态库:sudo yum install -y glibc-static

安装静态库之后,我们就可以通过 在已有的指令基础上加上-static指定静态库编译:

[hins@VM-12-13-centos testLinux]$ gcc test.c -o test2.s -static	# 静态编译指令
-rwxrwxr-x 1 hins hins   8360 Oct 29 20:41 test1.s # 动态编译
-rwxrwxr-x 1 hins hins 861288 Oct 29 20:41 test2.s # 静态编译[hins@VM-12-13-centos testLinux]$ file test1.s
test1.s: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0d515023c156fe158cca3be209a14ff5924814e1, not stripped[hins@VM-12-13-centos testLinux]$ file test2.s
test2.s: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, BuildID[sha1]=0c504898c44f70be42f625ac057dbc6ed3cae69b, not stripped

安装C++版本的gcc(g++):sudo yum install -y gcc-c++

安装C++静态库:sudo yum install -y libstdc++-static

🕒 4. Linux项目自动化构建工具-make/Makefile

🕘 4.1 背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual
    C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

🕘 4.2 使用

对于makefile,若想利用make命令,则必须创建makefile命名的文件(m大写也可),在内部编写一定的依赖规则之后,我们通过make就可以对应的执行程序,就省略了类似于这种gcc test.c -o test的编译指令,我们来看看如何操作:

[hins@VM-12-13-centos testLinux]$ touch makefile # 创建一个makefile文件
[hins@VM-12-13-centos testLinux]$ vim makefile # 编辑内部依赖关系
# 写入下面指令
mycode:mycode.c		# 依赖关系:即生成的mycode是依赖mycode.c实现的gcc mycode.c -o mycode		# 依赖方法:即上述我们需要省略的gcc指令,必须以Tab键开头
.PHONY:clean		# 被.PHONY修饰的对象是一个伪目标,它总是被执行,例子在下面
clean:rm -f mycode
[hins@VM-12-13-centos testLinux]$ make	# 这里make默认执行第一个gcc指令,生成mycode可执行文件,指令等价于make mycode
gcc mycode.c -o mycode
[hins@VM-12-13-centos testLinux]$ ll
total 24
-rw-rw-r-- 1 hins hins   74 Oct 30 11:32 makefile
-rwxrwxr-x 1 hins hins 8360 Oct 30 11:32 mycode		# 可执行文件
-rw-rw-r-- 1 hins hins   77 Oct 29 20:39 mycode.c[hins@VM-12-13-centos testLinux]$ ./mycode
Hello World!		# 输出结果[hins@VM-12-13-centos testLinux]$ make	# 重复执行make指令
make: `mycode' is up to date.		# 提示已是最新,不用再编译,原因是mycode.c没有任何修改[hins@VM-12-13-centos testLinux]$ make clean  # 执行clean对象
rm -f mycode
[hins@VM-12-13-centos testLinux]$ ll
total 12
-rw-rw-r-- 1 hins hins  74 Oct 30 11:32 makefile
-rw-rw-r-- 1 hins hins  77 Oct 29 20:39 mycode.c
[hins@VM-12-13-centos testLinux]$ make clean	# mycode文件已删除,但仍能执行,原因是被.PHONY修饰的对象总是被执行
rm -f mycode

🕒 5. Linux的第一个小程序-进度条

🕘 5.1 缓冲区概念

先运行以下两个代码

#include<stdio.h>
int main()
{// 首先执行的一定是printf,代码是顺序结构// 先执行printf不等于数据先显示printf("Heeeeello!\n");		// 第一个printf("Heeeeello!");		// 第二个sleep(2);return 0;
}

请添加图片描述
我们发现,sleep尽管在printf语句的后面,但是执行不带\n的代码中显示器是仍然是先执行的sleep,这是什么原因呢?

实际上,这是一个行缓冲的问题,即确实在语言上先执行的printf,但却不是直接打印在显示器上,而是进入了缓冲区,而缓冲区是以\n为截止条件的,也就是说这一行中程序如果没有\n,就会暂时保留在缓冲区内部,直到出现\n或者程序执行完成。因此,上面的动图并没有直接执行printf是因为没有\n。

🕘 5.2 回车换行概念

对于回车换行,实际上是两个概念,换行\n是换到下一行,而回车\r是光标回到这一行的起始位置,因此我们键盘上的enter键称之为回车换行实际上是两个功能合并在了一起。

🕘 5.3 fflush(stdout)

因此为了解决上面的代码问题,可以用刷新缓冲区的办法实现:

#include<stdio.h>
int main()
{printf("Heeeeello!\r");		fflush(stdout);sleep(2);return 0;
}

🕘 5.4 倒计时实现

#include<stdio.h>
#include<unistd.h>
int main()
{int cnt = 10;while(cnt){printf("倒计时:%2d\r", cnt);fflush(stdout);cnt--;sleep(1);}return 0;
}

上述实际上有一定的细节,我们知道/r只是回到起始位置,但如果不控制格式2d,就会出现打印10,90,80……的情况,因为我们每次只覆盖了第一个位置,因此在这里要控制格式,并且fflush(stdout)。
请添加图片描述

🕘 5.5 进度条实现

对于进度条来说,通过最上面的行缓冲的知识,我们已经知道应该如何去规避了,因此在这里直接展示进度条,我将程序分成三个部分,即经典的main.c/process.c/process.h,并且将makefile中的依赖对象也改变,对于依赖对象来说,只要-o后面最靠近的是要生成的即可。

# Makefile
ProcessOn:main.c process.c gcc -o ProcessOn main.c process.c -DN=3  # 利用命令行传参,选择进度条的形状.PHONY:clean 
clean:rm -f ProcessOn
// process.h
#pragma once
#include<stdio.h>
#include<string.h>
#include<unistd.h>      // usleep的头文件#define NUM 101
#define S_NUM 5extern void ProcessOn();  // 函数的声明
// process.c
#include"process.h"char style[S_NUM] = {'-','.','#','>','+'};void ProcessOn()    // 函数的定义
{int cnt = 0;char bar[NUM];memset(bar,'\0',sizeof(bar));//reverseconst char* lable = "|\\-/";//101次while(cnt <=100){//printf("[%-100s][%d%%][%c]\r", bar,cnt,lable[cnt%4]);printf("\033[42;34m[%-100s][%d%%][%c]\033[0m\r", bar,cnt,lable[cnt%4]); 		// 修改颜色fflush(stdout);bar[cnt++] = style[N];usleep(50000);}printf("\n");
}

颜色修改
printf(“'\033[字背景颜色;字体颜色m字符串\033[0m” ); printf(“'\033[47;31mhelloworld\033[5m”);

// main.c
#include"process.h"
int main()
{ProcessOn();  // 函数调用return 0;
}

请添加图片描述

🕒 6. git的使用

  • git clone + [url]:克隆远程仓库,这里的 url 就是项目的链接.

.gitignore介绍:凡是这个文件内部的后缀,都不会被上传到gitee上的。

所谓的git仓库,本质就是一个目录,以及里面的内容。而push到远端就是将.git的内容同步到gitee上

  • git add + 文件:将新增的文件添加到本地仓库
  • git commit [-m] "日志":提交,-m 后面加上提交的日志
  • git push:将本地内容推送到远端
  • git log:查看提交日志
  • git status:查看当前状态
  • git pull:把远端拉到本地同步。(如果远端和本地都同步进行修改了,起冲突了,直接先pull一下)

配置免密码提交
🔎 git本地免密码和账号pull、push

🕒 7. gdb(调试工具)的使用

Linux gcc/g++ 出来的二进制程序,默认是 release 模式
要使用 gdb 调试,必须在源代码生成二进制程序的时候 , 加上 -g 选项,这样才能进入Debug模式

安装gdb

sudo yum install -y gdb

程序的发布方式有两种, debug 模式和 release 模式
Linux gcc/g++ 出来的二进制程序,默认是 release 模式
要使用 gdb 调试,必须在源代码生成二进制程序的时候 , 加上 -g 选项

准备一份测试代码

// mytest.c
#include <stdio.h>
#include <time.h>void Print(int sum)
{long long  timestamp = time(NULL);printf("result = %d, timestamp: %lld\n", sum, timestamp);
}int AddToVal(int from, int to)
{int sum = 0;for(int i = from; i < to; i++){sum += i;}return sum;
}int main()
{int sum = AddToVal(0, 100);printf("hello a\n");printf("hello b\n");printf("hello c\n");printf("hello d\n");printf("hello e\n");printf("hello f\n");Print(sum);return 0;
}
# Makefile
mytest_g:mytest.cgcc -o mytest_g mytest.c -g --std=c99   # gcc默认支持c89标准,若要支持c99需要加上--std=c99
.PHONY:clean
clean:rm -f mytest_g

进入gdb:gdb mytest_g

常见选项

  • l + 行号:从指定的行号开始往下显示源代码,每次显示10行 (l – list);(注:gdb 有自动记忆命令的功能,即当我们第一次使用 l 显示源代码后,我们下一次再使用 l 或者下一次按下 enter 键时,它会接着上次的位置往下显示)
(gdb) l			# 每次显示10行(此处位置是随机)
warning: Source file is more recent than executable.
15	        sum += i;
16	    }
17	
18	    return sum;
19	}
20	
21	
22	int main()
23	{
24	    int sum = AddToVal(0, 100);
(gdb) l 0		# 从第1行开始显示
1	#include <stdio.h>
2	#include <time.h>
3	
4	void Print(int sum)
5	{
6	    long long  timestamp = time(NULL);
7	    printf("result = %d, timestamp: %lld\n", sum, timestamp);
8	}
9	
10	int AddToVal(int from, int to)
(gdb) l			# 第二次接着上次的位置往后显示
11	{
12	    int sum = 0;
13	    for(int i = from; i < to; i++)
14	    {
15	        sum += i;
16	    }
17	
18	    return sum;
19	}
20	
(gdb) 			# 使用enter键相当于执行上次的命令
21	
22	int main()......
  • l + 函数:列出某个函数的源代码 (l – list);
  • b + 行号:在某一行打一个断点,相当于VS中的F9 (b – breakpoint);
  • info b:查看断点;
  • d + 断点编号:删除断点 (d – delete);(注:每个断点都有自己的编号,我们删除断点时需要指明对应的断点编号)
  • r:调试运行,如果程序中有断点,则在断点处停下来,如果没有,则直接将程序跑完,相当于VS中的F5 (r – run);
  • n:逐过程调试,相当于VS中的F10 (n – next);
  • s:逐语句调试,相当于VS中的F11 (s – step);
  • c:运行至下一个断点处停下 (c – continue);(注:如果断点所在行不是一条语句,比如 “{” “}” 或者 空行,那么它会继续往下到有效行处停下 )
  • bt:查看调用堆栈 (breaktrace);
  • p + 变量:查看变量值 (p – print);
  • display/undisplay + 变量:跟踪查看一个变量,每次停下来都显示它的值,undisplay 取消对先前设置的那些变量的跟踪;
  • finish:把当前函数运行完;
  • disable breakpoints:禁用断点;
  • enable breakpoints:启用断点;
  • until + X行号:跳至X行
  • info(i) locals:查看当前栈帧局部变量的值
  • quit:退出 gdb;
(gdb) b 24
Breakpoint 1 at 0x400628: file mytest.c, line 24.
(gdb) b 26
Breakpoint 2 at 0x400644: file mytest.c, line 26.
(gdb) b 31
Breakpoint 3 at 0x400676: file mytest.c, line 31.
(gdb) info b					# 查看断点信息
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x0000000000400628 in main at mytest.c:24
2       breakpoint     keep y   0x0000000000400644 in main at mytest.c:26
3       breakpoint     keep y   0x0000000000400676 in main at mytest.c:31
(gdb) r							# 相当于VS的F5
Starting program: /home/hins/testLinux/gdb_test/mytest_g Breakpoint 1, main () at mytest.c:24
24	    int sum = AddToVal(0, 100);
(gdb) s							# 相当于VS的F11
AddToVal (from=0, to=100) at mytest.c:12
12	    int sum = 0;
(gdb) n							# 相当于VS的F10
13	    for(int i = from; i < to; i++)
(gdb) bt						# 查看调用堆栈
#0  AddToVal (from=0, to=100) at mytest.c:13
#1  0x0000000000400637 in main () at mytest.c:24
(gdb) display i					# 监视窗口
1: i = 0
(gdb) display sum
2: sum = 0
(gdb) 
(gdb) n
15	        sum += i;
2: sum = 0
1: i = 0
(gdb) n
13	    for(int i = from; i < to; i++)
2: sum = 0
1: i = 0
(gdb) n
15	        sum += i;
2: sum = 0
1: i = 1
(gdb) n
13	    for(int i = from; i < to; i++)
2: sum = 1
1: i = 1
(gdb) n
15	        sum += i;
2: sum = 1
1: i = 2
(gdb) n
13	    for(int i = from; i < to; i++)
2: sum = 3
1: i = 2
(gdb) finish					# 把当前函数运行完
Run till exit from #0  AddToVal (from=0, to=100) at mytest.c:13
0x0000000000400637 in main () at mytest.c:24
24	    int sum = AddToVal(0, 100);
Value returned is $1 = 4950
(gdb) n
25	    printf("hello a\n");
(gdb) c
Continuing.
hello aBreakpoint 2, main () at mytest.c:26
26	    printf("hello b\n");
(gdb) c							# 运行至下一个断点停下
Continuing.
hello b
hello c
hello d
hello e
hello fBreakpoint 3, main () at mytest.c:31
31	    Print(sum);
(gdb) finish
The program is not being run.

OK,以上就是本期知识点“gcc/g++/gdb/git的使用”的知识啦~~ ,感谢友友们的阅读。后续还会继续更新,欢迎持续关注哟📌~
💫如果有错误❌,欢迎批评指正呀👀~让我们一起相互进步🚀
🎉如果觉得收获满满,可以点点赞👍支持一下哟~

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

发布四大战略举措,亚马逊云科技看准了中国云市场的哪些新机会?

导读&#xff1a;全球最大的云厂商&#xff0c;在中国的最新布局。 2022年10月13日&#xff0c;亚马逊云科技在线上举办2022中国峰会。亚马逊云科技不仅发布了云计算技术趋势展望&#xff0c;还宣布了深耕中国市场的四大战略举措&#xff1a;“连中外、襄百业、携伙伴、促绿色”…

【Java8新特性】函数式接口

目录1. 介绍1.1 FunctionInterface注解1.2 函数式接口的调用2. 函数式编程2.1 Lambda的延迟加载技术2.2 Lambda表达式的使用3. 常用的函数式接口3.1 Supplier生产型接口3.2 Consumer消费型接口默认方法&#xff1a;andThen3.3 Predicate条件判断接口3.4 Function普通函数接口默…

ASP.NET Core教程-跨域配置(CORS Configuration)

更新记录 转载请注明出处: 2022年11月1日 发布。 2022年11月1日 从笔记迁移到博客。说明 Cross-Origin Resource Sharing,跨域资源共享 配置方式 在ASP.NET Core中有2种方式配置跨越,中间件方式(middleware approach) 和 特性修饰方式(attributes approach)。 中间件方式…

在Jupyter Notebook中使用Matplotlib(Anaconda3)

Matplotlib&#xff08;官网 Matplotlib — Visualization with Python &#xff09;是一个用于创建二维图形的Python库&#xff0c;它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形。将Jupyter Notebook于Matplotlib结合使用效果更好。 在Anaconda3的Jupyter …

HCL AppScan Standard漏洞扫描处理记录

官网&#xff0c;标准版应该是免费的&#xff0c;下载了标准版&#xff0c;没提示激活啥的&#xff0c;最近处理客户的漏洞扫描问题&#xff0c;主要就是修改nginx配置&#xff0c;各种查资料&#xff0c;不停的扫描验证&#xff0c;简单记录下吧。 APP简单使用 app快速下载地…

flutter 系列之:flutter 中的幽灵offstage

文章目录简介Offstage详解Offstage的使用总结简介 我们在使用flutter的过程中&#xff0c;有时候需要控制某些组件是否展示&#xff0c;一种方法是将这个组件从render tree中删除&#xff0c;这样这个组件就相当于没有出现一样&#xff0c;但是有时候&#xff0c;我们只是不想…

技术革新,取代传统会议模式?原来这么简单

随着AI人工智能的盛行&#xff0c;各领域面临前所未有的技术革新。人脸识别作为人工智能的一项重要技术&#xff0c;为工作及生活带来极大便捷&#xff0c;增效赋能。 人脸签到技术5大优势 01.人脸识别稳定&#xff0c;即使在光源不佳、角度受限的环境下也能精准识别&#xff1…

Libuv 各个回调(异步)事件的调用时机

Libuv 各个回调&#xff08;异步&#xff09;事件的调用时机 uv_close、uv_timer_start uv_close中注册的回调事件&#xff08;close_cb&#xff09;查阅官网API文档&#xff0c;Handle句柄是调用uv_close便会立即关闭&#xff0c;而注册的回调事件将推迟到下一次Loop循环中执…

设计模式——创建型模式

五大-创建型模式一、单例模式1、简介2、单例模式八种方式2.1、饿汉式&#xff08;静态常量&#xff09;2.2、饿汉式&#xff08;静态代码块&#xff09;2.3、懒汉式&#xff08;线程不安全&#xff09;2.4、懒汉式&#xff08;线程安全&#xff0c;加同步方法&#xff09;2.5、…

C2 实验 学习笔记

C2 实验 免责声明 本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关. C2隐藏技术 CDN 准备 一台 vultr centos7 机器一个域名cloudflare 账号 挂上 cdn 在域名购买后配置&#xff0c;cf 中的域名解析&#xff0c;在 cf 中配置…

「MySQL高级篇」MySQL之MVCC实现原理事务隔离级别的实现

①MVCC定义,用处,快照读,当前读 ②MVCC实现原理:隐藏字段,readview,undo log ③readview访问规则 ④事务隔离级别的具体实现大家好,我是melo,一名大三后台练习生,死去的MVCC突然开始拷打我🤣🤣🤣!🍳引言 MVCC,非常顺口的一个词,翻译起来却不是特别顺口:多…

Fiddler 抓包工具

1 基本使用 官网下载地址&#xff1a;Download Fiddler Web Debugging Tool for Free by Telerik X.1 电脑端监听 我们双击打开软件&#xff0c;进入到如下的一个界面&#xff0c;然后点击某一个请求&#xff0c;你会发现请求的内容是一堆明显不对的文字&#xff0c;然后该请求…

MySQL性能优化和慢查询日志

目标 了解性能优化的方案能够使用慢日志定位慢SQL 讲解 1. 优化方案 1.1 为什么要优化数据库性能 ​ MySQL凭借着出色的性能、低廉的成本、丰富的资源&#xff0c;已经成为绝大多数互联网公司的首选关系型数据库。可以看到Google&#xff0c;Facebook&#xff0c;Twitter&…

【百度地图】百度地图的使用方法 和 在vue中如何使用百度地图(超详细)

【百度地图】百度地图的使用方法 和 在vue中如何使用百度地图&#xff08;超详细&#xff09; 1- 介绍 百度地图功能强大&#xff0c;本篇文章只是对百度地图JavaScript API 进行一个介绍~ 官方网址 百度地图开放平台LBS&#xff1a;LocationBusinessServer 基于定义位置的商…

Spark 离线开发框架设计与实现

一、背景 随着 Spark 以及其社区的不断发展&#xff0c;Spark 本身技术也在不断成熟&#xff0c;Spark 在技术架构和性能上的优势越来越明显&#xff0c;目前大多数公司在大数据处理中都倾向使用 Spark。Spark 支持多种语言的开发&#xff0c;如 Scala、Java、Sql、Python 等。…

Matlab神经网络函数newff()新旧用法差异

在Matlab R2010a版中,如果要创建一个具有两个隐含层、且神经元数分别为5、3的前向BP网络,使用旧的语法可以这样写:net1 = newff(minmax(P), [5 3 1]); 注意minmax()函数的使用,还有对输出层神经元数(1)的指定。当然也可以采用新的语法,更简洁(请留意差异):net2 = new…

形态分类行为中的气泡佯谬

“假设光归根结底是波&#xff0c;只是给我们以粒子的印象&#xff0c;因为粒子吸收光波的能量是以离散的包的方式。波从源头传播出去像一个越来越大正在膨胀的气泡&#xff0c;到达一个原子时&#xff0c;气泡破裂&#xff0c;波坍缩并把所有的能量集中在一个地方&#xff0c;…

【数字式时间继电器】TR-23 DC110V

系列型号 TR-20数字式时间继电器&#xff1b;TR-21数字式时间继电器&#xff1b; TR-22数字式时间继电器&#xff1b;TR-23数字式时间继电器&#xff1b; TR-24数字式时间继电器&#xff1b;TR-25数字式时间继电器&#xff1b; TR-20D数字式时间继电器&#xff1b;TR-21D数字式…

无刷电机控制基础(3)——FOC矢量控制入门

本节我们讲一些无刷电机FOC矢量控制的入门知识。 1&#xff09;FOC矢量控制的作用 我们前两节讲的无刷电机&#xff08;BLDC&#xff09;&#xff0c;是最简单的结构&#xff0c;当转子匀速转动时&#xff0c;定子内产生的反电动势是梯形波&#xff1b;在驱动无刷电机转动时&a…

你不知道的JavaScript-----强制类型转换

目录 值类型转换 抽象值的操作 JSON 字符串化 ToNumber&#xff1a; 非数字值到数字值 Number(value) ToBoolean: 转换为布尔类型 Boolean(value) 强制类型转换 字符串和数字之间的显式强制类型转换 奇特的~运算符 字位截除 显式解析数字字符串 显式转换为布尔值 隐…