【小沐学C++】C++ 常用命令行开发工具(Linux)

15 篇文章 0 订阅

1、简介

编译的四个阶段:预处理(扩展各个宏与文件)、编译(得到汇编代码)、汇编(得到机器码)、链接(得到可执行文件)
在这里插入图片描述

预处理:编译处理宏定义等宏命令(eg:#define)——生成后缀为“.i”的文件   
编译:将预处理后的文件转换成汇编语言——生成后缀为“.s”的文件   
汇编:由汇编生成的文件翻译为二进制目标文件——生成后缀为“.o”的文件   
连接:多个目标文件(二进制)结合库函数等综合成的能直接独立执行的执行文件——生成后缀为“.out”的文件

在这里插入图片描述
在这里插入图片描述

2、gcc / g++

The GNU Compiler Collection includes front ends for C, C++, Objective-C, Fortran, Ada, Go, and D, as well as libraries for these languages (libstdc++,…). GCC was originally written as the compiler for the GNU operating system. The GNU system was developed to be 100% free software, free in the sense that it respects the user’s freedom.

在这里插入图片描述

实际使用中我们更习惯使用 gcc 指令编译 C 语言程序,用 g++ 指令编译 C++ 代码。需要强调的一点是,这并不是 gcc 和 g++ 的区别,gcc 指令也可以用来编译 C++ 程序,同样 g++ 指令也可以用于编译 C 语言程序。

GCC 编译器已经为我们提供了调用它的接口,对于 C 语言或者 C++ 程序,可以通过执行 gcc 或者 g++ 指令来调用 GCC 编译器。

当然,gcc 指令也为用户提供了“手动指定代表编译方式”的接口,即使用 -x 选项。例如,gcc -xc xxx 表示以编译 C 语言代码的方式编译 xxx 文件;而 gcc -xc++ xxx 则表示以编译 C++ 代码的方式编译 xxx 文件。

但如果使用 g++ 指令,则无论目标文件的后缀名是什么,该指令都一律按照编译 C++ 代码的方式编译该文件。也就是说,对于 .c 文件来说,gcc 指令以 C 语言代码对待,而 g++ 指令会以 C++ 代码对待。但对于 .cpp 文件来说,gcc 和 g++ 都会以 C++ 代码的方式编译。

gcc -v
g++ -v

在这里插入图片描述

# gcc 编译c代码
gcc demo.c
gcc main.c func.c -o app.out

# gcc 编译c++代码
gcc -xc++ -lstdc++ -shared-libgcc demo.cpp 
gcc -xc++ -lstdc++ -shared-libgcc demo.cpp -o democpp.exe

# g++ 编译c++代码
g++ demo.cpp
g++ demo.cpp -o democpp.exe

首先说明:gcc 和 GCC 是两个不同的东西

GCC:GNU Compiler Collection(GUN 编译器集合),它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。
gcc是GCC中的GUN C Compiler(C 编译器)
g++是GCC中的GUN C++ Compiler(C++编译器)

在这里插入图片描述
gcc 命令的常用选项:

选项解释
-ansi只支持 ANSI 标准的 C 语法。这一选项将禁止 GNU C 的某些特色, 例如 asm 或 typeof 关键词。
-c只编译并生成目标文件。
-DMACRO以字符串"1"定义 MACRO 宏。
-DMACRO=DEFN以字符串"DEFN"定义 MACRO 宏。
-E只运行 C 预编译器。
-g生成调试信息。GNU 调试器可利用该信息。
-IDIRECTORY指定额外的头文件搜索路径DIRECTORY。
-LDIRECTORY指定额外的函数库搜索路径DIRECTORY。
-lLIBRARY连接时搜索指定的函数库LIBRARY。
-m486针对 486 进行代码优化。
-o FILE生成指定的输出文件。用在生成可执行文件时。
-O0不进行优化处理。
-O 或 -O1优化生成代码。
-O2进一步优化。
-O3比 -O2 更进一步优化,包括 inline 函数。
-shared生成共享目标文件。通常用在建立共享库时。
-static禁止使用共享连接。
-UMACRO取消对 MACRO 宏的定义。
-w不生成任何警告信息。
-Wall生成所有警告信息。

2.1 system(执行shell 命令)

头文件:
#include<stdlib.h>
定义函数:
int system(const char * string);
函数说明:
system()会调用fork()产生子进程,由子进程来调用/bin/sh-c string来执行参数string字符串所代表的命令,此命令执行完后随即返回原调用的进程。

test_sys.c:

#include<stdlib.h>
#include<stdio.h>

int 
main(int argc, char *argv[])
{
	system("ls -al /etc/docker /etc/nginx /etc/firefox");
	return 0;
}
gcc test_sys.c -o test.exe
./test.exe

在这里插入图片描述

2.2 popen(建立管道I/O)

头文件
#include<stdio.h>
定义函数
FILE * popen( const char * command,const char * type);
函数说明
popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c 来执行参数command的指令。参数type可使用“r”代表读取,“w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。

test_popen.c:

#include<stdio.h>

main()
{
	FILE* fp;
	char buffer[80];
	fp=popen("cat /etc/nginx", "r");
	fgets(buffer,sizeof(buffer),fp);
	printf("%s", buffer);
	pclose(fp);
}

gcc test_popen.c -o test.out
./test.out

在这里插入图片描述

2.3 vfork+exec(新建子进程)

使用vfork()新建子进程,然后调用exec函数族。
test_vfork.c:

#include<unistd.h>
#include<stdio.h>

main()
{
    char * argv[]={"ls", "-al", "/etc/firefox", (char*)0 };
   
    if(vfork() == 0)
    {
        execv("/bin/ls", argv);
    }else{        
        printf("it is the parent process\n");
    }
}
gcc test_vfork.c -o test.out
./test.out

在这里插入图片描述

3、clang

The Clang project provides a language front-end and tooling infrastructure for languages in the C language family (C, C++, Objective C/C++, OpenCL, CUDA, and RenderScript) for the LLVM project. Both a GCC-compatible compiler driver (clang) and an MSVC-compatible compiler driver (clang-cl.exe) are provided. You can get and build the source today.
https://clang.llvm.org/

Clang是一个C语言、C++、Objective-C语言的轻量级编译器。源代码发布于BSD协议下。Clang将支持其普通lambda表达式、返回类型的简化处理以及更好的处理constexpr关键字。
在这里插入图片描述

Clang是一个C++编写、基于LLVM、发布于LLVM BSD许可证下的C/C++/Objective-C/Objective-C++编译器。它与GNU C语言规范几乎完全兼容(当然,也有部分不兼容的内容,包括编译命令选项也会有点差异),并在此基础上增加了额外的语法特性,比如C函数重载(通过__attribute__((overloadable))来修饰函数),其目标(之一)就是超越GCC。
在这里插入图片描述
win10 的 msvc,Ubuntu 的 gcc 和 clang
gcc 是c的编译器,g++是c++的编译器。

3.1 下载和安装clang

# yum install epel-release
yum install clang

在这里插入图片描述
在这里插入图片描述

检查是否安装成功(查看clang版本,有显示即为成功):

clang --version
clang -v

在这里插入图片描述

3.2 clang和gcc比较

3.2.1 gcc

GCC(GNU Compiler Collection,GNU编译器套装),是一套由GNU开发的编程语言编译器。它是一套以GPL及LGPL许可证所发布的自由软件,也是GNU项目的关键部分,亦是自由的类Unix及苹果电脑Mac OS X 操作系统的标准编译器。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。

GCC原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC很快地扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,以及Go与其他语言。

原本用C开发,后来因为LLVM、Clang的崛起,令GCC更快将开发语言转换为C++。许多C的爱好者在对C++一知半解的情况下主观认定C++的性能一定会输给C,但是Taylor给出了不同的意见,并表明C++不但性能不输给C,而且能设计出更好,更容易维护的程序。

3.2.2 clang

Clang(发音为/ˈklæŋ/类似英文单字clang) 是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。它采用了底层虚拟机(LLVM)作为其后端。它的目标是提供一个GNU编译器套装(GCC)的替代品。作者是克里斯·拉特纳,在苹果公司的赞助支持下进行开发,而源代码授权是使用类BSD的伊利诺伊大学厄巴纳-香槟分校开源码许可。

Clang项目包括Clang前端和Clang静态分析器等。

3.2.3 LLVM

“ LLVM , 它是一个 编译器 的基础建设,以 C++ 写成。它是为了任意一种编程语言写成的程序,利用 虚拟技术 ,创造出 编译时期 , 链结时期 , 运行时期 以及“闲置时期”的优化。

因为GCC的编译器已经慢慢无法满足苹果的需求,因此,苹果开发了Clang与LLVM来完全取代GCC,Xcode4之后,苹果的默认编译器已经是LLVM了。Clang作为编译器前端,LLVM作为编译器后端。

4、make

无论是在linux 还是在Unix环境 中,make都是一个非常重要的编译命令。

Make工具最主要也是最基本的功能就是通过makefile文件来描述源程序之间的相互关系并自动维护编译工作。而makefile 文件需要按照某种语法进行编写,文件中需要说明如何编译各个源文件并连接生成可执行文件,并要求定义源文件之间的依赖关系。

make --version
make -v

在这里插入图片描述
–f :指定作为makefile的文件的名称。 如果不用该选项,那么make程序首先在当前目录查找名为makefile的文件,如果没有找到,它就会转而查找名为Makefile的文件。如果您在Linux下使用GNU Make的话,它会首先查找GNUmakefile,之后再搜索makefile和Makefile。按照惯例,许多Linux程序员使用Makefile,因为这样能使Makefile出现在目录中所有以小写字母命名的文件的前面。

4.1 例子1

  • Makefile文件内容如下:
all:
	gcc -Wall test.c -o test.out

执行命令如下:

make
# or
make all

在这里插入图片描述

  • Makefile文件内容如下:
all:
	gcc -c -Wall test.c 
	gcc -Wall test.o -o test.out

执行命令如下:

make

在这里插入图片描述

  • Makefile文件内容如下:
all:
	gcc -c -Wall test.c 
	gcc -c -Wall anotherTest.c 
	gcc -Wall test.o anotherTest.o -o test.out

执行命令如下:

make

在这里插入图片描述

4.2 例子2

  • Makefile文件内容如下:
all: test 

test: test.o anotherTest.o 
	gcc -Wall test.o anotherTest.o -o test.out

test.o: test.c 
	gcc -c -Wall test.c 

anotherTest.o: anotherTest.c 
	gcc -c -Wall anotherTest.c 

clean: 
	rm -rf *.o test.out

执行命令如下:

make all
make test
make clean

在这里插入图片描述
通过 -B 选项让所有目标总是重新建立:

make -B

在这里插入图片描述
使用 -d 选项打印调试信息:

make -d | more

在这里插入图片描述
使用 -C 选项改变目录:
你可以为 make 命令提供不同的目录路径,在寻找 Makefile 之前会切换目录的。
但是你想运行的 make 命令的 Makefile 文件保存在 …/make-dir/ 目录下,你可以这样做:

make -C ../make-dir/

通过 -f 选项将其它文件看作 Makefile:

make -f my_makefile

4.3 问题汇总

可能出现的问题如下:
“Makefile:1: *** 遗漏分隔符 。 停止。”?

5、cmake

CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。只是 CMake 的组态档取名为 CMakeLists.txt。
在这里插入图片描述

5.1 下载cmake

在这里插入图片描述
ubuntu系统下只需要如下一句命令即可:

# ubuntu
sudo apt install cmake

CMake 提供了多种版本,包括但不限于 “RC 版本”(Release Candidate)和“稳定版本”(Latest Release)。切换到系统存放源代码的目录,再用 curl 命令通过该链接将 CMake 的二进制分发压缩包下载下来:

cd /usr/local/src

curl -LO https://github.com/Kitware/CMake/releases/download/v3.22.2/cmake-3.22.2-linux-x86_64.tar.gz

# or
yum install -y wget
wget -c https://github.com/Kitware/CMake/releases/download/v3.22.2/cmake-3.22.2-linux-x86_64.tar.gz
# wget -c https://cmake.org/files/v3.26/cmake-3.26.0-rc1-linux-x86_64.tar.gz

在这里插入图片描述

5.2 安装cmake

CMake 二进制分发压缩包下载完毕后,运行以下两条命令将压缩包解压缩,并将得到的文件夹移动到系统的本地程序目录,同时将文件夹重命名为 cmake(即 /usr/local/cmake):

tar -xvf cmake-3.26.0-rc1-linux-x86_64.tar.gz
# tar zxvf cmake-3.22.2-linux-x86_64.tar.gz
mv cmake-3.26.0-rc1-linux-x86_64 /usr/local/cmake

在这里插入图片描述
在这里插入图片描述
查看安装后的路径:

ls /usr/local/cmake

在这里插入图片描述

如果你是第一次按照本文步骤安装 CMake,为方便之后运行 CMake 的相关命令,请运行以下两条命令将 CMake 的可执行文件目录添加到系统环境变量 PATH 中:

echo 'export PATH="/usr/local/cmake/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

在这里插入图片描述
查看~/.bashrc:

vi ~/.bashrc
#在最后添加export PATH=/usr/local/cmake/bin:$PATH

在这里插入图片描述

查看cmake的版本:

cmake --verison

在这里插入图片描述

6、gdb

GDB是一个强大的命令行调试工具。虽然X Window提供了GDB的图形版DDD,但是我仍然更钟爱在命令行模式下使用GDB。

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具。或许,各位比较喜欢那种图形界面方式的,像VC、BCB等IDE的调试,但如果你是在 UNIX平台下做软件,你会发现GDB这个调试工具有比VC、BCB的图形化调试器更强大的功能。所谓“寸有所长,尺有所短”就是这个道理。
一般来说,GDB主要帮忙你完成下面四个方面的功能:

1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。
2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)
3、当程序被停住时,可以检查此时你的程序中所发生的事。
4、动态的改变你程序的执行环境。
gdb

在这里插入图片描述
一般来说GDB主要调试的是C/C++的程序。要调试C/C++的程序,首先在编译时,我们必须要把调试信息加到可执行文件中。使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点。如:

gcc -g hello.c -o hello
g++ -g hello.cpp -o hello

如果没有-g,你将看不见程序的函数名、变量名,所代替的全是运行时的内存地址。

# 在进入函数func时,设置一个断点。可以敲入break func,或是直接就是b func
gdb
b main

在这里插入图片描述

7、git

Git — The stupid content tracker, 傻瓜内容跟踪器。Linus Torvalds 是这样给我们介绍 Git 的。
在这里插入图片描述
Git 是用于 Linux内核开发的版本控制工具。与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持(wingeddevil注:这得分是用什么样的服务端,使用http协议或者git协议等不太一样。
在这里插入图片描述

并且在push和pull的时候和服务器端还是有交互的。),使源代码的发布和交流极其方便。 Git 的速度很快,这对于诸如 Linux kernel 这样的大项目来说自然很重要。 Git 最为出色的是它的合并跟踪(merge tracing)能力。

在这里插入图片描述

7.1 下载和安装git

Git是目前流行的非常好用的版本控制工具,这里介绍两种安装方式,1、yum安装,2、从github上下载最新的源码编译后安装。

在Linux上是有yum安装Git,非常简单,只需要一行命令:

yum -y install git

在这里插入图片描述

输入 git --version查看Git是否安装完成以及查看其版本号:

git --version

在这里插入图片描述
当然我们也可以从GitHub上下载最新的源码编译后安装。

# 需要删除旧的Git
yum -y remove git
# 下载,https://github.com/git/git/releases
wget https://github.com/git/git/archive/refs/tags/v2.39.1.tar.gz
# 进入/usr/local 目录解压git文件
tar -zxvf v2.39.1.tar.gz
# 安装编译所需要的依赖。
yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel gcc perl-ExtUtils-MakeMaker
# 编译git源码,进入cd /usr/local/git-2.39.1 目录
make prefix=/usr/local/git all
# 安装git至/usr/bin/git路径
make prefix=/usr/local/git install
# 配置环境变量
vi /etc/profile 
# 在底部加上如下
export PATH=$PATH:/usr/bin/git/bin
# 刷新环境变量
source /etc/profile
# 查看Git是否安装完成
git --version

在这里插入图片描述
在这里插入图片描述

7.2 使用git

命令功能
git init在本地的当前目录里初始化git仓库
git status查看当前仓库的状态
git add -A增加目录中所有的文件到缓存区
git add file增加相应文件到缓存区
git commit -m “信息”将缓存区中更改提交到本地仓库
git log查看当前版本之前的提交记录
git reflog查看HEAD的变更记录,包括回退
git branch -b branch_name建立一个新的分支
git diff查看当前文件与缓存区文件的差异
git checkout – file取消更改,将缓存区的文件提取覆盖当前文件
git reset --hard 版本号回退到相应版本号,同样也可以回退到未来的版本号
git clean -xf删除当前目录中所有未追踪的文件
git config --global core.quotepath false处理中文文件名

常用命令如下:

git remote add origin git@github.com:<用户名>/<仓库名>.git
git pull origin master //因为github建立仓库时会有readme.md文件,先要拷贝一份
git push -u origin master //将本地仓库链接到master分支上,你当然可以链接到其他分支
git push //上传你的本地仓库

8、bash

Bash Shell脚本是用Bash编写的计算机程序,它是一个包含了自定义数量命令的纯文本文件,用于在Linux系统上自动循环执行重复性任务。

8.1 Centos bash: 运行 ./xxx.sh: 权限不够

编写脚本xxx.sh:

#! /bin/bash
echo 'hello world';

在这里插入图片描述
在这里插入图片描述

chmod 777 ./xxx.sh
# chmod u+x test.sh
./xxx.sh

或者

chmod +x ./xxx.sh

或者

# 该方式不需要在第一行指定解释器信息
/bin/sh xxx.sh
# or 
sh xxx.sh
sh /root/test.sh

8.2 Linux中解决cannot access ‘\r’: No such file or directory

碰到这种情况,是因为脚本文件在windows环境下编辑过后再上传到linux服务器导致换行符格式不对。使用dos2unix命令行即可解决。
Ubuntu系统打开Windows下生成的文本文件,会在每行的末尾出现’^M’
原因就是Windows和Linux的回车符是不同的。

 在Windows下回车符是\r\n回车换行
 在Linux下回车符是\n

最简单、最常用的解决方法是使用dos2unix命令转换:

## ubuntu
apt-get install dos2unix
# or
apt-get install tofrodos

## centos
#进入root用户后,使用
yum install dos2unix。

在这里插入图片描述
dos2unix命令 用来将DOS格式的文本文件转换成UNIX格式的(DOS/MAC to UNIX text file format converter)。DOS下的文本文件是以\r\n作为断行标志的,表示成十六进制就是0D 0A。而Unix下的文本文件是以\n作为断行标志的,表示成十六进制就是0A。DOS格式的文本文件在Linux底下,用较低版本的vi打开时行尾会显示^M,而且很多命令都无法很好的处理这种格式的文件,如果是个shell脚本,。而Unix格式的文本文件在Windows下用Notepad打开时会拼在一起显示。因此产生了两种格式文件相互转换的需求,对应的将UNIX格式文本文件转成成DOS格式的是unix2dos命令。

dos2unix [-hkqV] [-c convmode] [-o file ...] [-n infile outfile ...]

-k:保持输出文件的日期不变
-q:安静模式,不提示任何警告信息。
-V:查看版本
-c:转换模式,模式有:ASCII, 7bit, ISO, Mac, 默认是:ASCII。
-o:写入到源文件
-n:写入到新文件
# 最简单的用法就是dos2unix直接跟上文件名
dos2unix file
# 如果一次转换多个文件
dos2unix file1 file2 file3
dos2unix -o file1 file2 file3
# 如果想把转换的结果保存在别的文件
dos2unix -n oldfile newfile
# 如果要保持文件时间戳不变
dos2unix -k file
dos2unix -k file1 file2 file3
dos2unix -k -o file1 file2 file3
dos2unix -k -n oldfile newfile
# 转换当前目录下所有文件
find -type f | xargs dos2unix

也可以使用*通配符来同时修改多个,或者使用空格隔开文件名的方式。

8.3 readelf查看可执行文件信息

readelf命令,一般用于查看ELF格式的文件信息,常见的文件如在Linux上的可执行文件,动态库(.so)或者静态库(.a) 等包含ELF格式的文件。以下命令的使用是基于android编译出来的so文件上面去运行。

  • 选项 -h(elf header),显示elf文件开始的文件头信息。
readelf -h ./test007.out

在这里插入图片描述

  • 选项 -l(program headers),segments 显示程序头(段头)信息(如果有数据的话)。
readelf -l ./test007.out

在这里插入图片描述

  • 选项 -S(section headers),sections 显示节头信息(如果有数据的话)。
readelf -S ./test007.out

在这里插入图片描述

  • 选项 -s,symbols 显示符号表段中的项
readelf -s ./test007.out

在这里插入图片描述

  • 选项 -r,relocs 显示可重定位段的信息。
readelf -r ./test007.out
  • 选项 -d,dynamic 显示动态段的信息。
readelf -d ./test007.out
  • 选项 -A,arch-specific 显示CPU构架信息。
readelf -A ./test007.out
  • 选项 -a,all 显示全部信息,等价于 -h -l -S -s -r -d -V -A -I。
readelf -a ./test007.out
  • 选项 -H,help 显示readelf所支持的命令行选项。
readelf -H ./test007.out
  • 选项 -V,version-info 显示版本段的信息。
readelf -V ./test007.out

在这里插入图片描述

8.4 常见Shell的种类

Linux Shell的种类很多,用户可以通过查看/etc/shells文件中的内容来查看自己主机中当前有哪些种类的Shell。

cat /etc/shells

在这里插入图片描述
Linux系统的shell作为操作系统的外壳,为用户提供使用操作系统的接口。它是命令语言、命令解释程序及程序设计语言。

shell是用户和Linux内核之间的接口程序,如果把Linux内核想象成一个球体的中心,shell就是围绕内核的外层。当从shell或其他程序向Linux传递命令时,内核会做出相应的反应。

shell是一个命令语言解释器,它拥有自己内建的shell命令集,shell也能被系统中的其他应用程序所调用。用户在提示符下输入的命令都由shell先解释然后传给Linux核心。

Linux中的shell有多种类型,常见的有Bourne Again Shell (简称bash)、Bourne Shell(简称sh)、C-Shelll(简称csh)、Korn Shell(简称ksh)。

sh是Unix最初使用的shell,并且在每种Unix上都可以使用。sh在shell编程方面相当优秀,但在处理与用户的交互方面做得不如csh和ksh。Linux默认的shell是bourne again shell(bash),它与sh完全向后兼容。bash放在bin/bash中。sh和bash都是Linux上的默认shell,而bash是sh的升级版。

结语

如果您觉得该方法或代码有一点点用处,可以给作者点个赞,或打赏杯咖啡;╮( ̄▽ ̄)╭
如果您感觉方法或代码不咋地//(ㄒoㄒ)//,就在评论处留言,作者继续改进;o_O???
如果您需要相关功能的代码定制化开发,可以留言私信作者;(✿◡‿◡)
感谢各位大佬童鞋们的支持!( ´ ▽´ )ノ ( ´ ▽´)っ!!!

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值