【9.模块化开发和代码重用之——头文件、动静态库】

news2024/9/27 21:23:35

目录

  • 前言
  • 软件工程的基本原则
  • 程序的模块化开发和代码重用技术
  • 开发自己的头文件
    • 定义实现自己的头文件
    • 编写实现文件(源文件)
    • 编译代码
    • 链接目标文件到可执行文件
  • 实现类似标准库效果的几种方法
  • 实际使用的开发方法
    • 头文件库
  • 尝试自动链接静态库(好像每次都还是要指定库的名字)
    • 生成静态库
    • 配置环境变量(可选)
    • 编译链接程序
      • 使用命令行链接静态库并编译
      • 配置构建任务task.json文件编译并链接
    • 配置编译器设置
    • 对应文件
  • 尝试自动链接动态库
    • 配置环境变量(非常重要)
      • 在用户环境变量下的Path变量里放入自己的库的路径
      • 系统环境变量也是如此操作
      • LD_LIBRARY_PATH
    • 生成动态库文件
    • 配置构建任务task.json
  • 效果
  • 待续

前言

温馨提示:前面都是一些介绍性的内容,为的是今后可以继续拓展类似的技术,具体技术可以看第四节开发自己的头文件

在了解GUI的时候发现好像可以使用链接库的技术实现自己定义、实现自己的库函数,并且在代码中包含头文件即可。于是.开始了解这方面的内容。发现静、动态链接库属于程序的模块化开发和代码重用的内容,后者又属于软件工程的基本原则

软件工程的基本原则

软件工程是一门应用工程原则、方法和技术来开发、运行和维护软件的学科。它包括一系列的原则和实践,旨在提高软件的质量和生产效率。以下是一些软件工程的基本原则:

  • 模块化:将软件分解成独立的、可管理的模块,以便于开发、测试和维护。

  • 抽象:通过抽象隐藏复杂性,只暴露必要的接口。

  • 信息隐藏:隐藏模块内部的实现细节,只公开必要的接口。

  • 可维护性:设计易于理解和修改的软件。

  • 可测试性:确保软件可以被有效地测试。

  • 重用性:尽可能重用已有的代码和组件,以减少开发时间和成本。

  • 配置管理:管理软件的版本和变更,确保软件的一致性和可追溯性。

  • 持续集成:频繁地将代码集成到主分支,以尽早发现和解决问题。

  • 风险管理:识别、评估和缓解项目风险。

  • 质量保证:确保软件满足质量标准和用户需求。

  • 用户参与:在整个开发过程中,让用户参与决策和测试。

  • 迭代开发:通过多次迭代逐步完善软件,每次迭代都包括需求分析、设计、编码、测试和部署。

  • 文档化:编写清晰、完整的文档,以支持软件的开发、使用和维护。

  • 性能优化:确保软件在性能上满足用户的需求。

  • 安全性:设计安全的软件,以防止未授权访问和数据泄露。

  • 可扩展性:设计能够适应未来需求变化的软件。

程序的模块化开发和代码重用技术

这篇文章只简要介绍一下动静态库的概念 ,主要还是实现功能,具体的功能作用后续会写

  • 动态链接库(Dynamic LInk LIbrary)

是一种微软公司在Windows操作系统中实现共享函数库的方式。DLL文件中包含了可由多个程序同时使用的代码和数据,这些程序不必包含实际的代码,而是在运行时调用DLL中包含的代码。

代码共享多个程序可以共享同一个DLL中的代码,这样可以减少内存占用和磁盘空间。

便于维护和更新:如果DLL中的代码需要更新或修复,只需更新DLL文件,所有使用该DLL的程序都可以获得更新,而不需要重新编译或更新每个程序

性能优化:DLL可以被设计为在需要时才加载,这样可以减少程序的启动时间。

本地化:DLL可以用于本地化应用程序,例如,可以有多个语言版本的DLL,应用程序根据用户的地区设置加载相应的DLL

Linux系统中

在Linux系统中,动态链接库通常以.so(Shared Object)作为扩展名这些库在程序运行时被动态加载,允许多个程序共享同一库文件,节省内存和磁盘空间。Linux使用ldconfig工具来管理动态链接库的搜索路径,并通过/etc/ld.so.conf和LD_LIBRARY_PATH环境变量来指定库文件的位置。可以使用gcc命令配合-shared和-fPIC选项来创建动态链接库。

Windows
Windows系统中的动态链接库以.dll(Dynamic Link Library)作为文件扩展名。Windows使用PE(Portable Executable)作为其可执行文件和动态链接库的格式。在Windows中,动态链接库的创建通常通过Microsoft Visual Studio进行,使用/LD选项来编译DLL。

  • 静态链接库(Static Libraries):

静态链接库在编译时将库代码直接集成到可执行文件中,这可以减少运行时的依赖,但会增加可执行文件的大小。
静态库(.a 文件在Unix-like系统中,或 .lib 文件在Windows系统中)

  • 对象文件(Object Files):

对象文件包含编译后但未链接的代码。它们可以被重复使用,以避免重新编译源代码。

  • 框架(Frameworks):

在某些操作系统(如macOS)中,框架是一种特殊的库,它包含了代码、资源和头文件,用于支持应用程序的特定功能。

  • 服务化(Services):

将功能封装为服务,通过网络调用。这种模式允许跨平台和跨语言的服务重用。

  • 微服务架构(Microservices):

将应用程序分解为一组小服务,每个服务实现特定功能,并通过API进行通信。

  • 插件系统(Plugin Systems):

允许用户或开发者通过插件来扩展应用程序的功能,插件可以在运行时动态加载。

  • 组件化(Componentization):

将软件系统分解为可重用的组件,这些组件可以通过不同的方式组合来构建应用程序。

  • 面向对象编程(Object-Oriented Programming, OOP):

通过类和对象的概念,实现代码的封装、继承和多态,从而提高代码的重用性。

  • 设计模式(Design Patterns):

设计模式是解决特定问题的通用方法,它们提供了一种模板,可以用来构建模块化和可重用的设计。

  • 代码生成工具(Code Generation Tools):

这些工具可以根据模板或规则自动生成代码,减少手动编写重复代码的工作。

  • 模板(Templates):

在编程语言中,模板是一种用于创建通用数据结构或算法的方式,它们可以在不同的上下文中重复使用。

  • 函数式编程(Functional Programming):

通过不可变数据和高阶函数,函数式编程鼓励代码的重用和模块化。

  • 依赖注入(Dependency Injection):

一种设计模式,允许将模块间的依赖关系明确地传递给组件,而不是让组件自行查找或创建它们需要的资源。

  • 软件包管理器(Package Managers):

如npm、Maven、pip等,它们允许开发者共享和重用代码库,同时管理项目依赖。

  • 代码片段和代码库(Code Snippets and Repositories):

开发者可以创建和分享代码片段,其他人可以在需要时复制和粘贴这些代码。

开发自己的头文件

头文件中通常包含了函数声明、宏定义、类型定义、模板声明等,它们可以被多个源文件包含(#include),从而使得在不同的源文件中可以使用相同的函数、类型和宏。

头文件的使用是C语言模块化编程的基础,它们使得代码更加组织化和可重用。通过将函数和宏的定义放在头文件中,可以在不同的源文件中多次使用而无需重复编写相同的代码。这是一种代码重用的简单而有效的方法,也是上面提到的“组件化”和“面向对象编程”中封装原则的体现。

定义实现自己的头文件

我们的目的是能够像使用标准库那样可以通过包含头文件的方式就可以使用里面的库函数,而且里面的功能还要我们自己定制。

首先我们创建一个头文件并编写内容,在头文件中,声明你想要提供的函数、定义宏、声明类型等

#ifndef CONVERT_H
#define CONVERT_H
void printBinary(unsigned int num);
#endif

编写实现文件(源文件)

#include "convert.h"
#include <stdio.h>


void printBinary(unsigned int num) {

    if (num == 0) {
        printf("0");
        return ;
        
    }
    
    if (num > 0) {
        printBinary(num >> 1);
        printf("%d", num&1);//取最低位打印
    }
}

编译代码

gcc -c convert.c -o convert.o

这样做完之后,在其他源文件中就可以包含创建的头文件,并通过编译器将其链接到程序中从而升成可执行文件 main.o

链接目标文件到可执行文件

gcc main.c convert.o -o main

但是会发现,这样做的话,每次都需要将自己的库链接到自己的程序中,我觉得是比较麻烦的,我们可以发现标准库不需要每次都显示链接库,因为这些库是运行时环境的一部分,已经预先编译链接到系统中了。在C语言中,标准库函数大多数是由编译器提供,并且与编译器一起安装的。这些函数的实现通常包含在编译器的运行时库中,而不是由用户程序在编译时链接。

实现类似标准库效果的几种方法

那么如何让自己的库也能实现这样的效果呢,有以下几种方法:

  • 静态库:

将你的代码编译成静态库(.a 文件在Unix-like系统中,或 .lib 文件在Windows系统中)。
在编译时,使用编译器的 -static 选项将库静态链接到你的可执行文件中。

  • 创建共享(动态库)库:

将你的代码编译成共享库(.so 文件在Unix-like系统中,或 .dll 文件在Windows系统中)。
将共享库放置在系统的库搜索路径中,如 /usr/lib 或 /usr/local/lib。
使用 ldconfig(在Unix-like系统中)更新动态链接器的缓存。

  • 安装到标准路径:

将你的库文件安装到操作系统的标准库路径下,如 /usr/lib 或 /usr/local/lib。
确保头文件位于标准包含路径下,如 /usr/include 或 /usr/local/include。

  • 修改链接器配置:

修改系统的链接器配置文件,如 /etc/ld.so.conf(在Unix-like系统中),并运行 ldconfig 来更新链接器的缓存。

  • 环境变量:

设置环境变量,如 LD_LIBRARY_PATH(在Unix-like系统中)或 PATH(在Windows系统中),以包含你的库文件所在的目录。
使用pkg-config:

  • 创建 pkg-config 文件

这是一个帮助库维护者和开发者管理编译和链接标志的工具。
用户可以使用 pkg-config 工具来获取编译和链接你的库所需的标志。

  • 集成到编译器:

如果你有能力,可以与编译器开发商合作,将你的库集成到编译器的运行时库中。

  • 发布为系统软件包:

为你的操作系统创建软件包(如 .deb、.rpm、.pkg),这样用户可以通过包管理器安装你的库。


除了静态库和共享库之外,其他方法可能需要管理员权限或对系统有更深入的了解。此外,修改系统级别的文件和配置可能会对系统的稳定性和安全性产生影响,因此在进行这些操作时应格外小心。

实际使用的开发方法

头文件库

直接将头文件放到标准库路径下C:\Program Files\mingw64\x86_64-w64-mingw32\include
然后在头文件里面就写好对应的函数实现

这种方式通常称为“头文件库”或“内联库”。这样做的好处是,用户在使用你的库时,只需要包含头文件即可,无需进行额外的链接步骤。这种方式在一些小型库或者模板库中非常常见。

我看stdio.h也是这样实现的

注意事项

代码膨胀:将实现放入头文件会导致每个包含该头文件的源文件都会有一份库函数的实现代码,这可能会导致编译后的二进制文件体积增大

宏定义:使用宏定义来防止头文件被重复包含是必要的,如示例中的#ifndef、#define和#endif。

内联函数:如果库函数很小,可以考虑使用inline关键字,这可以使得编译器尝试将函数内联到每个调用点,从而减少函数调用的开销

标准路径:确保你的头文件位于编译器的搜索路径中,这样编译器才能正确找到并包含它。


尝试自动链接静态库(好像每次都还是要指定库的名字)

对于标准库,是编译器自带的库,比如 C 标准库(libc),这些库在编译时会自动链接到的程序中,不需要显式指定链接这些库。

而对于静态库,是一组编译好的函数和数据的集合,它们在编译时被整合到程序中。使用静态库时,需要在编译命令中指定静态库的路径和名称,以便编译器知道如何链接这些库。

也就是说无论如何都要链接的

那么就有两种方式来编译链接了,一种是用命令行,一种是使用文件,其实本质上都是一样的,但是使用task.json文件配置会更加方便

生成静态库

ar rcs libdatatest.a file1.o file2.o file3.o

这里就是使用file1-file3目标文件生成libdatatest静态库

配置环境变量(可选)

LIBRARY_PATH 或 LD_LIBRARY_PATH(对于动态库),这样编译器和链接器会自动在这些路径中查找库文件。
在系统变量或者用户变量中建立变量名分别为LIBRARY_PATH 和LD_LIBRARY_PATH的变量,值就填库的路径。

这个非常关键,特别是动态库,如果不配置环境变量会一直找不到库

编译链接程序

使用命令行链接静态库并编译

gcc main.c -o 3-testCLib-static -L 
C:/Users/Administrator/Desktop/nosee/code/c/2024-C-Code/3-文件 -ldatatest

这个命令指定将main.c 编译成3-testCLib-static.exe可执行文件

  • -L 后面指定的是库的路径 如果是-L.的话就是在当前工程目录下寻找库
  • -l 后面跟着的是库的名字 我的库的名字是libdatatest.lib 但是这里需要输入datatest

配置构建任务task.json文件编译并链接

这个文件定义了编译和运行任务,还包括库文件的搜索路径,以及 -l 参数来链接特定的库。
指定头文件路径也是必要的 否则会显示找不到头文件

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: gcc.exe 生成活动文件",
			"command": "C:/Program Files/mingw64/bin/gcc.exe",
			"args": [
				"-fexec-charset=GBK",//防止中文输出乱码
				"-fdiagnostics-color=always",
				"-g",
				"${workspaceFolder}\\*.c",
				"-o",
				"${workspaceFolder}\\${workspaceRootFolderName}.exe",
				"-I", // 添加额外的头文件路径
       			 "C:/Program Files/mingw64/x86_64-w64-mingw32/myinclude",
				
				"-LC:/Program Files/mingw64/x86_64-w64-mingw32/mylib",
				"-ldatatest"
			],
			"options": {
				"cwd": "${workspaceFolder}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": "build",
			"detail": "编译器: \"C:/Program Files/mingw64/bin/gcc.exe\""
		}
	]
}

这样就定义好了库文件的搜索路径和该链接哪个库,就可以直接用快捷键执行生成任务而不需要人为用命令行来链接了

如果有多个库文件需要链接的话 需要按顺序一个个写

gcc -o my_program my_program.c -L/usr/local/lib -lmath 
-L/usr/lib -lxml2 -lsqlite3

配置编译器设置

在 VSCode 中,c_cpp_properties.json 文件用于配置 C/C++ 项目的 IntelliSense 功能,包括编译器路径、包含路径等。你可以通过 Ctrl+Shift+P 打开命令面板,然后输入 “C/C++: Edit Configurations (UI)” 来编辑这个文件。在这里,你可以设置 includePath 来指定编译器搜索头文件的路径,以及 compilerPath 来指定编译器的路径。如果不写包含头文件的路径的话,优先搜索标准库的头文件

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                 "C:/Program Files/mingw64/x86_64-w64-mingw32/myinclude"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "windowsSdkVersion": "10.0.19041.0",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "compilerPath": "C:/Program Files/mingw64/bin/gcc.exe",

            "intelliSenseMode": "gcc-x64"
        }
    ],
    "version": 4
}

对应文件

c_cpp_properties.json中对应路径的文件夹下放好对应的源文件和头文件,这样就可以转定义看到实现了,也可以看到自己的头文件

在这里插入图片描述

在对应task.json的库文件存放的路径下放好对应的静态库
在这里插入图片描述

这样以后只需要在task.json中修改需要链接的库就好了。虽然还是要选择自己要链接的库,但是已经比以前方便很多了。

尝试自动链接动态库

配置编译器设置是一样的,也就是c_cpp_properties.json,因为这个配置对于目前的工程来说就是指定编译器和头文件路径

需要注意的点是动态库必须配置环境变量,而且配置后电脑重启才能生效,所以做完这步最好重启一下电脑,否则怎么都会找不到库的

配置环境变量(非常重要)

在用户环境变量下的Path变量里放入自己的库的路径

在这里插入图片描述

系统环境变量也是如此操作

LD_LIBRARY_PATH

最好也在系统环境变量下新建一个名字叫LD_LIBRARY_PATH的变量 内容也是动态库的路径

这三步做完记得重启,这样电脑就会在这个路径下去搜索动态库了

生成动态库文件

gcc -c myprint.c -o myprint.o -fpic
gcc myprint.o -o libmyprint.dll -shared -fpic
gcc -c main.c -o main.o -I C:/Program Files/mingw64/x86_64-w64-mingw32/myinclude

配置构建任务task.json

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "cppbuild",
			"label": "C/C++: gcc.exe 生成活动文件",
			"command": "C:/Program Files/mingw64/bin/gcc.exe",
			"args": [
				"-fexec-charset=GBK",//防止中文输出乱码
				"-fdiagnostics-color=always",
				"-g",
				"${workspaceFolder}\\*.c",
				
				"-I", // 添加额外的头文件路径
       			 "C:/Program Files/mingw64/x86_64-w64-mingw32/myinclude",

				"-LC:/Program Files/mingw64/x86_64-w64-mingw32/mylib",
				"-lmyprint",

				"-o",
				"${workspaceFolder}\\${workspaceRootFolderName}.exe",
			],
			"options": {
				"cwd": "${workspaceFolder}"
			},
			"problemMatcher": [
				"$gcc"
			],
			"group": "build",
			"detail": "编译器: \"C:/Program Files/mingw64/bin/gcc.exe\""
		}
	]
}

效果

在这里插入图片描述
从上面的图片可以看出我的工程文件是不包含头文件和源文件的,并且动态库也不在当前目录下,但是确可以通过转定义看到函数的实现和头文件,并且还可以正常执行调试

待续

本篇文章并没有深入介绍动静态库的区别,而且其实可以使用Cmake对需要链接的库、以及编译选项进行配置,日后再讲吧

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

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

相关文章

替换jar包中class文件

虽然.jar文件是一种Java归档文件&#xff0c;可以使用压缩软件打开&#xff0c;但是并不能通过压缩软件来修改其内容&#xff0c;只能通过jar命令来更新文件。 一、背景 在使用血氧仪SDK时出现了问题&#xff0c;经过分析是在申请权限时版本不兼容导致的闪退异常&#xff0c;…

大数据新视界 --大数据大厂之 Kylin 多维分析引擎实战:构建数据立方体

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

全国信息学奥赛泄题事件:一场对公平与公正的严峻考验

在科技与教育日益融合的今天&#xff0c;信息学奥林匹克竞赛作为选拔计算机科学领域未来人才的重要平台&#xff0c;始终承载着培养青少年逻辑思维、编程能力和创新潜力的重任。然而&#xff0c;2024年9月发生的一起全国CSP-J/S认证考试泄题事件&#xff0c;却如同一枚重磅炸弹…

SpringBoot教程(三十) | SpringBoot集成Shiro权限框架

SpringBoot教程&#xff08;三十&#xff09; | SpringBoot集成Shiro权限框架 一、 什么是Shiro二、Shiro 组件核心组件其他组件 三、流程说明shiro的运行流程 四、SpringBoot 集成 Shiro &#xff08;shiro-spring-boot-web-starter方式&#xff09;1. 添加 Shiro 相关 maven2…

领导让部署一个系统服务,我该怎么弄?

文章目录 Dockerdocker基础通过Dockerfile构建镜像打包镜像&#xff0c;离线使用docker修改代理内容 Nginxubuntu安装nginxnginx基本操作 问题Sqlalchemy可以反射一些表&#xff0c;另外一些反射为None查看服务器的架构和版本&#xff0c;查看本机外网IPPG数据库创建角色创建库…

CentOS7 离线部署docker和docker-compose环境

一、Docker 离线安装 1. 下载docker tar.gz包 下载地址&#xff1a; Index of linux/static/stable/x86_64/ 本文选择版本&#xff1a;23.0.6 2.创建docker.service文件 vi docker.service文件内容如下&#xff1a; [Unit] DescriptionDocker Application Container Engi…

SpringBoot中XXL-JOB实现灵活控制的分片处理方案

❃博主首页 &#xff1a; 「码到三十五」 &#xff0c;同名公众号 :「码到三十五」&#xff0c;wx号 : 「liwu0213」 ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a…

9.25盒马鲜生一面

1.自我介绍 2.css两种盒子模型 ​3.rem和em 4.px概念 5.transition和animation的区别 6.移动端适配方案 7.vh、vw、% 8.js基本数据类型 9.call、apply、bind的区别 10.js实现继承的方法 11.get和post的区别 12.web安全&#xff08;XSS&#xff0c;CSRF&#xff09; …

甩锅笔记:好好的服务端应用突然起不来,经定位是无法访问外网了?测试又说没改网络配置,该如何定位?

在工作中、团队协作时&#xff0c;可能遇到的问题&#xff0c;如集成测试等场景。但是作为偏前端的全栈&#xff0c;锅从天上来&#xff0c;不是你想甩就能甩&#xff0c;尤其面对测试等比较强势的团体&#xff08;bug创造者&#xff09;&#xff0c;你必须有强大的心理承受能力…

Vscode Run Code Py中文乱码问题

F1打开命令行界面&#xff0c;找到settings.json文件&#xff1b;选Workspace这个 找/直接输"code-runner.executorMap" python值改为"$pythonPath $fullFileName"

进程和线程的区别;线程的多种创建方式;Thread 类及常见方法;线程的状态

文章目录 进程和线程的区别线程的创建方式继承Thread&#xff0c;重写run&#xff08;创建单独的类/匿名内部类&#xff09;实现Runnable&#xff0c;重写run&#xff08;创建单独的类/匿名内部类&#xff09;实现Callable&#xff0c;重写call&#xff08;创建单独的类/匿名内…

828华为云征文 | 云服务器Flexus X实例,Docker集成搭建 Jupyter Notebook

828华为云征文 | 云服务器Flexus X实例&#xff0c;Docker集成搭建 Jupyter Notebook Docker 部署 Jupyter Notebook 是一个方便且快速的方式&#xff0c;可以帮助你搭建一个用于数据分析、机器学习和科学计算的环境 华为云端口放行 服务器放行对应端口9955 Docker安装并配置镜…

计算物理精解【1】-C++计算(1)

文章目录 基础hello,worldgetlinestd::cin引用与指针函数数据类型基本数据类型更多类型sizeof 正则表达式单次匹配多次匹配组匹配字符串的匹配 splitmap基础实战整型变量符号表简单分析生成整型变量表 正则表达式基础regex_matchregex_replaceswap Eigen概述简单例子Matrix基础…

DNS协议解析

DNS协议解析 什么是DNS协议 IP地址&#xff1a;一长串唯一标识网络上的计算机的数字 域名&#xff1a;一串由点分割的字符串名字 网址包含了域名 DNS&#xff1a;域名解析协议 IP>域名 --反向解析 域名>IP --正向解析 域名 由ICANN管理&#xff0c;有级别&#xf…

2.1 HuggingFists系统架构(二)

部署架构 上图为HuggingFists的部署架构。从架构图可知&#xff0c;HuggingFists主要分为服务器(Server)、计算节点(Node)以及数据库(Storage)三部分。这三部分可以分别部署在不同的机器上&#xff0c;以满足系统的性能需求。为部署方便&#xff0c;HuggingFists社区版将这三部…

Python | Leetcode Python题解之第419题棋盘上的战舰

题目&#xff1a; 题解&#xff1a; class Solution:def countBattleships(self, board: List[List[str]]) -> int:return sum(ch X and not (i > 0 and board[i - 1][j] X or j > 0 and board[i][j - 1] X)for i, row in enumerate(board) for j, ch in enumerat…

vue全局注册和局部注册的区别

1.全局注册&#xff1a; a、b为注册的组件 2.局部注册 3.有图可以看出&#xff0c;全局注册会影响白屏时间

2024最新Python Debugger工具pdb的用法(深度学习项目),了解输入输出的形状大小

侵入式方法 &#xff08;在被调试的代码中添加以下代码然后再正常运行代码&#xff09; import pdb pdb.set_trace() 例如&#xff1a; 正常运行训练文件后&#xff1a; 在命令行发现输出以下内容&#xff1a; 出现了(Pdb) 的提示符&#xff0c;说明已经打开pdb 在使用Pyth…

解决fatal: unable to access ‘https://........git/‘: Recv failure: Operation time

目录 前言 解决方法一 解决方法二 解决方法三 解决方法四 总结 前言 在使用 Git 进行代码拉取时&#xff0c;可能会遇到连接超时的问题&#xff0c;特别是在某些网络环境下&#xff0c;例如公司网络或防火墙严格的环境中。这种情况下&#xff0c;Git 无法访问远程仓…

红帽认证会过期吗?一文给你解释清楚!

红帽认证以其权威性、实用性和高含金量受到了广大IT人士的青睐&#xff0c;尤其是Linux领域。然而&#xff0c;许多人在考取红帽认证后&#xff0c;心中都有一个疑问&#xff1a;红帽认证会过期吗?本文将为大家详细解答这个问题。 红帽认证是什么? 红帽认证是由红帽公司(Re…