linux下 c++ 类库创建

1.概述

2.创建过程 共享库、动态链接库

1.举例 在Linux下创建C++类库(通常是共享库或静态库)涉及到几个步骤。以下是一个基本的指南,展示了如何创建一个简单的共享库。

1. 编写源代码

首先,你需要编写你的C++类库的源代码。例如,我们有一个简单的MyClass.hMyClass.cpp文件。

MyClass.h

#ifndef MYCLASS_H  
#define MYCLASS_H  
  
class MyClass {  
public:  
    MyClass();  
    ~MyClass();  
    void doSomething();  
};  
  
#endif // MYCLASS_H

MyClass.cpp

2. 编译为共享库

使用g++编译器,你可以将你的代码编译为一个共享库(在Linux上通常是.so文件)。

g++ -fPIC -shared -o libmyclass.so MyClass.cpp

这里:

  • -fPIC:位置无关代码(Position Independent Code),这对于共享库是必需的。
  • -shared:指示g++生成一个共享库。
  • -o libmyclass.so:指定输出文件的名称。

3. 使用你的库

现在,你可以在其他C++程序中使用你的库了。你需要包含你的头文件,并在编译时链接到你的库。

main.cpp

#include "MyClass.h"  
  
int main() {  
    MyClass myObj;  
    myObj.doSomething();  
    return 0;  
}

编译并链接:

g++ main.cpp -L. -lmyclass -o myprogram

这里:

  • -L.:指定库文件的搜索路径(在当前目录)。
  • -lmyclass:链接到libmyclass.so库(注意不需要前缀lib和后缀.so)。
  • -o myprogram:指定输出文件的名称。

4. 运行你的程序

最后,运行你的程序:

./myprogram

你应该能看到你的类库中的代码正在运行。

注意事项:

  • 确保你的头文件和库文件在编译时是可用的。你可以使用-I选项来指定头文件的搜索路径。
  • 在生产环境中,你可能希望将你的库文件安装到标准位置(如/usr/local/lib),并使用包管理工具(如dpkgrpm)来管理它们。
  • 对于更复杂的项目,你可能希望使用构建系统(如MakefileCMakeBazel)来自动化编译和链接过程。

2.linux 下 c++ 类库有几种 

在Linux下,C++类库主要分为几大类,这些类库为开发者提供了丰富的功能和工具,以支持各种应用程序的开发。以下是对这些类库的简要介绍和分类:

  1. 标准库(Standard Library)
    • C++标准库是C++编程语言的一部分,包含了大量的类和函数,用于支持各种常见的编程任务。它包括了STL(Standard Template Library)容器、算法、迭代器等,以及一些基础的输入输出流、字符串处理、时间和日期等。
  2. 网络通信库
    • ACE(Adaptive Communication Environment):一个开源的、跨平台的框架,提供了用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++包装外观(Wrapper Facade)和框架组件。
    • Boost.Asio:一个基于Boost的异步I/O库,封装了对Socket的常用操作,简化了基于Socket程序的开发。
    • libevent:一个用C语言编写的网络库,主要支持类Linux操作系统,也支持Windows的IOCP。
  3. 跨平台GUI库
    • Qt:一个跨平台的应用程序和用户界面框架,广泛用于开发GUI应用程序。
    • JUCE:一个包含万象的C++类库,用于开发跨平台软件。
  4. 科学计算与并行处理库
    • ROOT:一个面向对象的框架,可以高效地处理和分析大量的数据,常用于科学计算。
    • 其他可能包括一些专门针对并行计算和科学计算的库,如OpenMP、Intel TBB等。
  5. XML和JSON处理库
    • 这些库提供了对XML和JSON数据的解析和生成功能,使得在C++中处理这些数据格式变得简单。
  6. 其他专用库
    • 根据应用程序的具体需求,可能还需要使用到一些专用的库,如加密库(OpenSSL)、数据库连接库(如MySQL Connector/C++)、图像处理库(如OpenCV)等。
  7. 静态库与动态库
    • 在Linux下,C++库通常以静态库(.a文件)或动态库(.so文件)的形式存在。静态库在编译时被直接链接到可执行文件中,而动态库则在运行时被加载。

需要注意的是,以上只是C++类库的一个大致分类,实际上还有许多其他的库和框架可供选择。在选择使用哪个库时,需要根据项目的具体需求和开发者的偏好来决定。

2.linux 下静态库、动态库、共享库是什么关系 

在Linux下,静态库、动态库和共享库之间的关系和概念可以概括如下:

  1. 静态库(Static Library)
    • 扩展名:通常以.a作为文件扩展名。
    • 链接方式:在编译时被链接到目标代码中的库文件,即被复制到可执行程序中。每个使用静态库的程序都会有库的一个副本。
    • 优缺点:
      • 优点:加载速度快,因为库已经被嵌入到可执行文件中;发布程序时无需额外提供库文件,因为库已经被包含在应用程序中。
      • 缺点:会导致可执行文件体积变大,浪费磁盘空间和内存资源;更新、部署、发布麻烦,因为每次修改库都需要重新编译和链接所有使用该库的程序。
  2. 动态库(Dynamic Link Library, DLL)
    • 在Linux上,动态库通常被称为共享库(Shared Library)
    • 扩展名:在Linux系统中,动态库或共享库的文件名通常以.so(Shared Object)结尾。
    • 链接方式:在程序编译的时候并不会被链接到目标代码中,而是在程序运行的时候才被载入。多个程序可以共享使用同一个动态库,节省了内存。
    • 优缺点:
      • 优点:链接时不复制,程序运行时由系统动态加载到内存,供程序调用;系统只加载一次,多个程序可以共用,节省内存;程序升级简单,只需要更新库文件,而无需重新编译和链接使用该库的程序。
      • 缺点:运行时需要依赖外部的动态库文件,如果库文件缺失或版本不匹配,可能会导致程序无法正常运行。
  3. 总结
    • 关系:动态库和共享库在Linux系统中是同一个概念的不同称呼,都指的是在程序运行时加载的库文件,可以被多个程序共享使用。而静态库则是在编译时被链接到目标代码中的库文件。
    • 选择:开发者在选择使用静态库还是动态库时,需要根据项目的具体需求来决定。如果项目需要独立运行,不依赖外部库文件,或者对性能有较高要求,可以选择使用静态库;如果需要提高代码的复用性和可维护性,或者需要节省磁盘空间和内存资源,可以选择使用动态库。

在Linux系统中,合理地使用静态库和动态库,可以提高程序的运行效率和灵活性,同时也方便开发者进行代码的管理和维护。

3.linux 编译的时候 类库的搜索范围是什么

在Linux下编译C++程序时,类库的搜索范围主要取决于几个关键因素,这些因素共同决定了链接器在何处查找所需的库文件。以下是类库搜索范围的详细解释:

  1. 编译器参数(如-L)
    • 使用-L参数可以指定链接器在编译时搜索库文件的目录。例如,如果你有一个库文件位于/home/user/libs目录下,你可以使用-L/home/user/libs来告诉链接器在那里查找库。
  2. 环境变量LIBRARY_PATH
    • LIBRARY_PATH环境变量指定了链接器在编译时搜索库文件的路径。这个环境变量可以包含多个由冒号分隔的目录。链接器会首先搜索这些目录中的库文件。
  3. 内定目录
    • 链接器还会搜索一些内定的目录,这些目录是在编译GCC时写入程序内的。对于大多数Linux系统,这些目录通常包括/lib/usr/lib/usr/local/lib
  4. 链接器参数-rpath和-rpath-link
    • -rpath参数允许你指定在程序运行时链接器应该搜索的库文件路径。这些路径会被嵌入到可执行文件中,因此在运行时,链接器会首先在这些路径中查找库文件。
    • -rpath-link参数与-rpath类似,但它仅用于编译时解析依赖关系,并不会影响运行时库文件的搜索路径。
  5. 环境变量LD_LIBRARY_PATH
    • LD_LIBRARY_PATH环境变量用于指定在程序运行时动态链接器应该搜索的库文件路径。这个环境变量主要用于在运行时覆盖默认的库文件搜索路径。然而,需要注意的是,虽然LD_LIBRARY_PATH很有用,但它可能会引入不可预测的行为或性能问题,因此在使用时需要谨慎。
  6. 配置文件/etc/ld.so.conf和/etc/ld.so.cache
    • /etc/ld.so.conf文件包含了动态链接器在运行时搜索库文件的目录列表。这些目录会被/sbin/ldconfig命令读取并生成一个缓存文件/etc/ld.so.cache,以提高动态链接器的搜索效率。
    • 当你修改了/etc/ld.so.conf文件或添加了新的库文件目录后,需要运行/sbin/ldconfig命令来更新/etc/ld.so.cache文件。

综上所述,Linux编译时类库的搜索范围包括编译器参数指定的目录、环境变量LIBRARY_PATH指定的目录、内定目录、链接器参数-rpath和-rpath-link指定的目录、环境变量LD_LIBRARY_PATH指定的目录以及配置文件/etc/ld.so.conf和/etc/ld.so.cache中指定的目录。这些搜索路径共同构成了链接器在编译和运行时查找库文件的范围。

4.c 编译动态链接库

在C语言中,你可以创建一个动态链接库(也称为共享库),这允许你在多个程序之间共享代码。以下是在Unix-like系统(如Linux或macOS)上使用GCC编译器创建动态链接库的基本步骤:

  1. 编写源代码

首先,你需要编写你的C源代码。例如,我们创建一个简单的函数,该函数接受两个整数参数并返回它们的和。将此代码保存为mylib.c

#ifndef MYLIB_H  
#define MYLIB_H  
  
int add(int a, int b);  
  
#endif //MYLIB_H

同时,你需要一个头文件(例如mylib.h)来声明这个函数:

#include "mylib.h"  
  
int add(int a, int b) {  
    return a + b;  
}
  1. 编译为动态链接库

使用GCC编译器,你可以通过以下命令将源代码编译为动态链接库:

gcc -shared -o libmylib.so mylib.c

这里,-shared选项告诉GCC你要创建一个共享库,-o libmylib.so指定输出文件的名称(在这种情况下是libmylib.so)。你可以根据需要更改这个名称。
3. 使用动态链接库

一旦你有了动态链接库,你就可以在其他C程序中使用它。为此,你需要在编译时包含库,并在运行时确保库在系统的库路径中或指定库的路径。

例如,如果你有一个名为main.c的程序,它使用了你的库中的函数,你可以这样编译它:

gcc -o main main.c -L. -lmylib

在这里,-L.告诉GCC在当前目录中查找库,-lmylib指定要链接的库(注意,-l选项后面的库名应去掉前面的lib和后缀.so)。
4. 运行程序

在运行程序之前,确保动态链接库在系统的库路径中,或者你可以通过设置LD_LIBRARY_PATH环境变量来指定库的路径。例如:

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./main

这将把当前目录添加到库路径中,然后你可以运行你的程序。

请注意,上述步骤是针对Unix-like系统的。如果你在Windows上,过程会有所不同,特别是库的命名和编译选项。在Windows上,你可能会使用.dll作为动态链接库的后缀,并使用不同的编译器选项来创建它们。

5.c 如何使用自定义的动态链接库 

在C语言中,使用自定义的动态链接库(也称为共享库)涉及几个步骤。这里是一个基本的指南,展示了如何在Unix-like系统(如Linux或macOS)上创建和使用自定义的动态链接库。

1. 编写源代码

首先,你需要编写库的源代码和头文件。

mylib.h(头文件):

#ifndef MYLIB_H  
#define MYLIB_H  
  
int add(int a, int b);  
  
#endif //MYLIB_H

mylib.c(源文件):

#include "mylib.h"  
  
int add(int a, int b) {  
    return a + b;  
}

2. 编译动态链接库

使用GCC编译器将源代码编译为动态链接库。

gcc -shared -o libmylib.so mylib.c

3. 编写使用库的程序

现在,你可以编写一个C程序来使用这个库。

main.c(使用库的程序):

#include <stdio.h>  
#include "mylib.h"  
  
int main() {  
    int sum = add(2, 3);  
    printf("The sum is: %d\n", sum);  
    return 0;  
}

4. 编译并链接到动态链接库

编译你的程序时,需要链接到你的动态链接库。你需要告诉编译器在哪里找到库文件(使用-L选项),以及要链接的库名(使用-l选项,注意去掉lib前缀和.so后缀)。

gcc -o main main.c -L. -lmylib

这里,-L.告诉编译器在当前目录中查找库。

5. 运行程序

在运行程序之前,你需要确保动态链接库在系统的库路径中,或者你可以通过设置LD_LIBRARY_PATH环境变量来指定库的路径。

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
./main

这里,:$LD_LIBRARY_PATH确保你不会覆盖现有的库路径。

如果你不想设置LD_LIBRARY_PATH,你可以将库文件复制到系统的标准库路径中,如/usr/local/lib(可能需要root权限)。或者,你可以在编译时使用-Wl,-rpath选项来指定运行时库的搜索路径。

6. 清理

在开发过程中,你可能想要清理生成的文件。你可以使用make工具或简单地使用rm命令来删除它们。

rm -f libmylib.so main

然后,你可以重新编译和链接你的库和程序。

6.export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH 啥意思

export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH 是一个在 Unix 和类 Unix 系统(如 Linux 和 macOS)上用于设置动态链接器(如 ld.so 或 ld-linux.so)在运行时查找共享库(动态链接库)的目录的 shell 命令。

这个命令做了以下几件事:

  1. 设置环境变量export 命令用于设置或导出环境变量,这样它们就可以被子进程(如你启动的程序)所访问。
  2. 指定新的 LD_LIBRARY_PATH 值:这里,我们为 LD_LIBRARY_PATH 分配了一个新的值。
  3. .(当前目录): 前面的 . 表示当前目录。当你执行 ./some_program 来运行一个程序时,它通常位于当前目录中。将 . 添加到 LD_LIBRARY_PATH 允许程序在当前目录中查找所需的共享库。
  4. $LD_LIBRARY_PATH:这是一个环境变量引用,表示 LD_LIBRARY_PATH 的当前值。在将 . 添加到 LD_LIBRARY_PATH 时,我们不想覆盖其现有的值(如果有的话),所以我们使用 $LD_LIBRARY_PATH 来保留它。
  5. : 作为分隔符:在 LD_LIBRARY_PATH 中,多个目录由冒号(:)分隔。

因此,export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH 的意思是:“将当前目录添加到 LD_LIBRARY_PATH 的开始位置,但保留 LD_LIBRARY_PATH 的任何其他现有值”。

这样做的一个常见原因是你正在测试或开发一个共享库,并且该库位于你当前的工作目录中。通过设置 LD_LIBRARY_PATH,你可以确保你的程序在运行时能够找到并使用这个库,而无需将其复制到系统的标准库目录中。

但请注意,依赖于 LD_LIBRARY_PATH 来找到共享库通常不是一个好主意,因为它使得程序的运行依赖于特定的环境设置。在生产环境中,你通常应该安装共享库到标准的系统库目录(如 /usr/lib 或 /usr/local/lib),或者使用其他方法来指定库的位置(如 ldconfig 或 -Wl,-rpath 链接器选项)。

7.c 编译时指定动态链接库的路径

在编译C程序时,如果你想指定动态链接库(共享库)的路径,你可以使用-L选项来告诉编译器在链接阶段到哪里查找库文件,并使用-l选项来指定要链接的库名(不包括前缀lib和后缀.so.a)。

但是,-L选项只影响编译时的库搜索路径,不会影响程序运行时动态链接器查找库文件的路径。如果你想在运行时指定库文件的搜索路径,你需要设置LD_LIBRARY_PATH环境变量。

编译时指定库路径

假设你的动态链接库文件是libmylib.so,并且它位于/path/to/libs目录下,你可以这样编译你的程序:

gcc -o myprogram main.c -L/path/to/libs -lmylib

这条命令告诉编译器在/path/to/libs目录下查找名为libmylib.so的库文件,并将其链接到你的程序myprogram中。

运行时指定库路径

如果你的程序在运行时找不到动态链接库,你可以通过设置LD_LIBRARY_PATH环境变量来指定库文件的搜索路径。例如:

export LD_LIBRARY_PATH=/path/to/libs:$LD_LIBRARY_PATH
./myprogram

这条命令将/path/to/libs添加到LD_LIBRARY_PATH环境变量的开始位置,以确保你的程序在运行时能够找到libmylib.so库文件。

使用-Wl,-rpath选项

另外,你还可以使用-Wl,-rpath选项来在编译时指定程序运行时库文件的搜索路径。这个选项将路径嵌入到可执行文件中,这样程序在运行时就会知道到哪里查找库文件。例如:

gcc -o myprogram main.c -L/path/to/libs -lmylib -Wl,-rpath,/path/to/libs

这条命令会在编译时将/path/to/libs路径嵌入到myprogram可执行文件中,这样程序在运行时就会首先在这个路径下查找libmylib.so库文件。注意,这种方式不依赖于LD_LIBRARY_PATH环境变量。

3.创建过程 静态链接库

1.c 静态链接库试验

在C语言中,静态链接库(static library)是一种包含多个目标文件(object files)的归档文件,这些目标文件是编译器编译源代码后产生的。静态链接库在编译时会被完全嵌入到最终的可执行文件中,因此最终的可执行文件不依赖于外部库文件。

下面是一个简单的步骤,演示如何创建一个C静态链接库,并使用它:

1. 编写源代码

首先,我们需要编写一些源代码。假设我们有两个源文件:lib_add.c 和 lib_sub.c,它们分别实现了加法和减法功能。

lib_add.c:

#include "lib_add.h"  
  
int add(int a, int b) {  
    return a + b;  
}

lib_add.h:

#ifndef LIB_ADD_H  
#define LIB_ADD_H  
  
int add(int a, int b);  
  
#endif // LIB_ADD_H

lib_sub.c:

#include "lib_sub.h"  
  
int sub(int a, int b) {  
    return a - b;  
}

lib_sub.h:

#ifndef LIB_SUB_H  
#define LIB_SUB_H  
  
int sub(int a, int b);  
  
#endif // LIB_SUB_H

2. 编译为目标文件

使用gcc编译器将源代码编译为目标文件:

gcc -c lib_add.c -o lib_add.o
gcc -c lib_sub.c -o lib_sub.o

这将会生成两个目标文件:lib_add.o 和 lib_sub.o

3. 创建静态链接库

使用ar命令将目标文件归档为静态链接库:

ar rcs libmath.a lib_add.o lib_sub.o

这将会生成一个名为libmath.a的静态链接库。

4. 编写主程序

现在我们可以编写一个主程序来使用这个静态链接库:

main.c:

#include <stdio.h>  
#include "lib_add.h"  
#include "lib_sub.h"  
  
int main() {  
    int a = 5, b = 3;  
    printf("Addition: %d\n", add(a, b));  
    printf("Subtraction: %d\n", sub(a, b));  
    return 0;  
}

5. 链接静态库并编译主程序

使用gcc编译器链接静态库并编译主程序:

gcc main.c -L. -lmath -o main

注意-L.告诉gcc在当前目录下搜索库文件,-lmath告诉gcc链接名为math的库(即libmath.a)。

6. 运行程序

现在我们可以运行程序了:

./main

如果一切正常,你应该会看到如下输出:

Addition: 8
Subtraction: 2

这表示你的静态链接库已经成功创建,并且你的主程序已经成功链接并使用了它。

 

4.关联工具

1.拷贝文件到指定路径 

在Unix-like系统(如Linux或macOS)中,你可以使用cp命令来拷贝文件到指定路径。以下是如何使用cp命令的基本示例:

拷贝单个文件

如果你想将文件source.txt拷贝到/path/to/destination/目录下,并且保持文件名不变,你可以这样做:

cp source.txt /path/to/destination/

拷贝文件并重命名

如果你想在拷贝时重命名文件,你可以指定新的文件名作为目标路径的一部分:

cp source.txt /path/to/destination/new_name.txt

拷贝目录及其内容

如果你想拷贝一个目录及其所有内容到另一个位置,你需要使用-r(或-R,它们是等价的)选项来递归地拷贝目录:

cp -r source_directory /path/to/destination/

这会将source_directory目录及其所有子目录和文件拷贝到/path/to/destination/下。如果目标位置已经存在同名目录,你可能会收到一些警告或错误,具体取决于你的系统和cp命令的版本。

注意事项

  • 确保目标路径存在。如果目标路径不存在,cp命令可能会失败或创建目标路径(如果你使用了像-p这样的选项来保持源文件的属性)。
  • 如果你没有权限写入目标位置,cp命令会失败。你可能需要使用sudo来获取必要的权限。
  • 在使用cp命令时,要小心不要覆盖重要文件。你可以使用-i选项来提示确认覆盖。

例如,以下命令会在覆盖文件之前提示你:

cp -i source.txt /path/to/destination/

 2.linux 创建目录

在Linux中,你可以使用mkdir命令来创建目录(也称为文件夹)。以下是一些基本的用法:

  1. 创建单个目录

如果你想要创建一个名为mydir的目录,你可以这样做:

mkdir mydir
  1. 创建多个目录

使用mkdir命令一次创建多个目录,你可以使用空格分隔目录名:

mkdir dir1 dir2 dir3
  1. 递归创建目录

如果你想要创建一个目录树,其中包含嵌套的子目录,你可以使用-p选项。例如,要创建/path/to/mydir,即使/path/path/to还不存在,你也可以这样做:

mkdir -p /path/to/mydir

-p`选项会确保在创建新目录之前,所有必要的父目录都存在。
4. 设置目录权限

你可以使用-m选项来指定新目录的权限。例如,要创建一个权限为755的目录,你可以这样做:

mkdir -m 755 mydir

注意:在Linux中,权限通常表示为三位数的八进制数,其中第一个数字代表所有者的权限,第二个数字代表组的权限,第三个数字代表其他用户的权限。755意味着所有者有读、写、执行权限,组和其他用户只有读和执行权限。
5. 显示创建目录的详细信息

使用-v选项(verbose)可以在创建目录时显示详细信息:

mkdir -v mydir

这将在创建目录时显示一条消息,告诉你目录已被创建。

2.显示当前路径 

在Linux中,你可以使用pwd(Print Working Directory)命令来显示当前路径。在终端中输入pwd并按下回车键,系统将输出你当前所在的目录路径。

例如:

$ pwd
/home/username

在这个例子中,/home/username 是当前用户的家目录路径。$ 是命令提示符,它表示你可以在这里输入命令。当你输入pwd并按下回车键后,命令提示符会移动到下一行,显示当前目录的路径。

3.”/usr/bin/ld: -lib1没有找到:没有这样的文件和目录“ 这里"/usr/bin/ld"是啥意思 

注意:不包括前缀 lib 和后缀 .so 或 .a

在Linux系统中,/usr/bin/ld 通常是链接器(linker)的路径,链接器是用于将编译后的目标文件(object files)和库文件(library files)组合成最终的可执行文件或共享库的工具。当你看到错误消息:

/usr/bin/ld: -lib1没有找到:没有这样的文件和目录

这通常意味着链接器在尝试链接你的程序时,找不到名为 lib1 的库文件或相关参数传递有误。这里的 -lib1 很可能是一个链接器选项或参数的一部分,但它被错误地解释了。

这个问题可能有几个原因:

  1. 拼写或路径错误:你可能想要链接的库文件名或路径拼写错误,或者没有正确地指定库的路径。

  2. 链接器选项格式错误:如果你想要链接一个库,你应该使用 -l 选项(小写L),后面跟着库名(不包括前缀 lib 和后缀 .so 或 .a)。例如,要链接名为 libexample.so 的库,你应该使用 -lexample

  3. 库文件不存在:指定的库文件可能不存在于你告诉链接器的位置。

为了解决这个问题,你可以:

  • 检查库文件的名称和路径是否正确。
  • 使用正确的链接器选项格式。
  • 确保库文件存在于你告诉链接器的位置,或者确保库文件的路径已经被添加到库搜索路径中(例如,通过 LD_LIBRARY_PATH 环境变量或链接器的 -L 选项)。

如果你确实想要链接一个名为 lib1 的库,并且该库文件位于标准库路径下(如 /usr/lib 或 /usr/local/lib),你应该使用 -l1(注意是小写L和数字1,而不是 -lib1)。如果库文件不在标准路径下,你需要使用 -L 选项指定库文件的路径。例如:

gcc -o myprogram main.o -L/path/to/libs -l1

在这个例子中,-L/path/to/libs 告诉链接器在 /path/to/libs 目录下查找库文件,而 -l1 则告诉链接器链接名为 lib1 的库(即查找 lib1.so 或 lib1.a)。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值