当前位置: 首页 > news >正文

C语言预处理艺术:编译前的魔法之旅

大家好,这里是小编的博客频道
小编的博客:就爱学编程

很高兴在CSDN这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!

本文目录

  • 引言
  • 正文
    • 一、预处理的作用与流程
      • (1)预处理阶段(Preprocessing)
      • (2)编译阶段(Compilation)
      • (3)汇编阶段(Assembly)
      • (4)链接阶段(Linking)
    • 二、预处理指令详解
      • (1)宏定义和宏替换
        • 《1》宏定义的基本概念
          • 1.1 无参数的宏定义
          • 1.2 带参数的宏定义
        • 《2》宏定义的特性与注意事项
          • 2.1 宏的文本替换特性
          • 2.2 宏的作用域与生命周期
          • 2.3 宏与函数的区别
        • 《3》高级宏技巧与应用案例
          • 3.1 宏串联与字符串化
      • (2)文件包含
        • 一、文件包含的基本概念
        • 二、`#include`指令的使用方式
        • 三、文件包含的优势与注意事项
          • (1)优势
          • (2)注意事项
        • 四、示例说明
  • 由于本文已经介绍很多了,所以小编在下一篇完结本节知识的介绍期待一下吧!!!!快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

引言

C语言预处理是C语言编译过程的一个重要阶段,它在源代码被正式编译之前对代码进行一系列的处理操作。这些处理包括宏替换、文件包含、条件编译等,旨在提高代码的移植性、可读性和可维护性。以下是关于C语言预处理有关的详细介绍。一起来看看吧!!!

在这里插入图片描述


那接下来就让我们开始遨游在知识的海洋!

正文


一、预处理的作用与流程

  • 预处理阶段主要处理源文件中以 # 开头的指令。这些指令告诉预处理器在编译之前需要对源代码进行哪些修改或调整。经过预处理后,生成一个中间文件(通常以.i为后缀),然后再进入正式的编译阶段。

  • 在C语言中,从源代码到可执行文件的转换过程通常分为四个阶段:预处理、编译、汇编和链接。下面是对这四个阶段的详细介绍

(1)预处理阶段(Preprocessing)

预处理是编译过程的第一个阶段,主要任务是对源代码中的预处理指令进行处理。这些指令通常以“#”开头,如#include#define等。

  • 1. 宏替换:预处理器会将代码中的宏(使用#define定义的内容)替换为实际的值或表达式。例如,将PI定义为3.14159后,预处理器会在代码中所有出现PI的地方将其替换为3.14159

  • 2. 文件包含:预处理器会处理#include指令,将指定头文件的内容插入到源文件中。这有助于代码的模块化,使得多个源文件可以共享相同的声明和定义。

  • 3. 条件编译:根据#ifdef#ifndef等条件编译指令,预处理器会决定是否编译某部分代码。这允许开发者根据不同的编译条件选择性地包含或排除特定的代码块。

  • 4. 删除注释:预处理阶段还会删除源代码中的所有注释,因为注释对编译器是不可见的,不参与编译。

经过预处理后的代码,通常是一个没有注释、完成了宏替换和头文件包含的文件,但扩展名仍然是.c


(2)编译阶段(Compilation)

在编译阶段,编译器会把预处理后的C语言代码转换为汇编代码。这一阶段的主要任务是进行语法分析和语义分析。

  • 1. 词法分析:编译器首先会将源代码分解为一系列的单词(token),如关键字、标识符、运算符等。这些单词将作为后续语法分析的输入。
  • 2. 语法分析:编译器会根据C语言的语法规则,将单词组合成语法结构,如表达式、语句、函数等。这一阶段的目标是验证源代码是否符合C语言的语法规则。
  • 3. 语义分析:在语法分析的基础上,编译器会进一步检查变量类型、函数调用等是否符合C语言的语义规则。同时,编译器还会生成中间表示(Intermediate Representation, IR),这是一种介于高级语言和机器语言之间的代码形式,便于后续的优化和代码生成。

编译阶段的输出结果是生成目标文件(object file),通常以.o.obj为后缀。这是一个二进制文件,包含了程序的机器码,但还不能直接运行。


(3)汇编阶段(Assembly)

  • 在汇编阶段,汇编器会将编译生成的中间代码转换成目标代码,即汇编指令。这些汇编指令与具体的硬件平台相关,因此汇编器的输出会因目标平台的不同而有所差异。

汇编阶段的主要任务是:

  • 将中间代码翻译成汇编指令;
  • 为源代码中的变量、函数等生成符号表,以便在链接阶段使用;
  • 生成目标文件,这是一个可以直接被链接器处理的二进制文件。

(4)链接阶段(Linking)

链接阶段是编译过程的最后一步,它的任务是将多个目标文件以及所需的库文件组合成一个可执行文件。

  • 1. 符号解析:链接器会查找并解析各个目标文件和库文件中的符号,如函数和变量的定义与调用。这是确保程序正确性的关键步骤之一。

  • 2. 地址分配:链接器会为每个符号分配内存地址,以确保程序中的函数调用和变量引用可以正确执行。

  • 3. 库链接:如果程序使用了外部的库(如标准C库或第三方库),链接器会将这些库的代码与目标文件链接在一起。

  • 4. 生成可执行文件:最终,链接器将所有目标文件和库文件整合成一个可以直接在操作系统上运行的可执行文件。这个文件的扩展名通常是.exe(在Windows系统上)或没有扩展名(在Linux/Unix系统上)。

通过以上四个阶段的处理,C语言的源代码最终被转换成了一个可以在计算机上运行的可执行文件


二、预处理指令详解

  • C语言的预处理阶段在编译之前对源代码进行一系列的处理操作,这些处理包括宏替换、文件包含、条件编译等。小编先介绍宏定义的相关知识,并通过丰富的代码示例来详细阐述其用法和注意事项。

(1)宏定义和宏替换

《1》宏定义的基本概念
  • 宏定义是C语言中一种常用的预处理指令,它允许程序员为一段代码或数据定义一个别名(即宏)。在编译过程中,预处理器会将这些宏替换为它们所代表的实际内容。宏定义通常使用#define指令来实现。
1.1 无参数的宏定义
  • 无参数的宏定义是最简单的宏类型,它直接将一个标识符替换为一个指定的字符串或数值。这种宏常用于定义常量或简化复杂的表达式。

例:

#include <stdio.h>// 定义一个表示圆周率的宏
#define PI 3.14159265358979323846int main() {double radius = 5.0;double area = PI * radius * radius; // 使用PI宏计算圆的面积printf("The area of the circle is: %f
", area);return 0;
}
  • 在这个例子中,PI被定义为一个表示圆周率的常量。在main函数中,我们使用这个宏来计算圆的面积。

1.2 带参数的宏定义

带参数的宏定义允许我们创建更灵活的宏,这些宏可以接受参数并在替换时将它们插入到相应的位置。这种宏类似于函数,但它们在预处理阶段就被展开,而不是在运行时调用。

#include <stdio.h>// 定义一个计算两个数最大值的宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))int main() {int x = 10, y = 20;int max_value = MAX(x, y); // 使用MAX宏计算最大值printf("The maximum value between %d and %d is: %d
", x, y, max_value);return 0;
}

在这个例子中,MAX宏接受两个参数ab,并返回它们之间的较大值。在main函数中,我们使用这个宏来计算xy之间的最大值。


《2》宏定义的特性与注意事项

虽然宏定义提供了强大的功能,但在使用时也需要注意一些特性和潜在的问题

2.1 宏的文本替换特性
  • 宏替换是在预处理阶段进行的文本替换操作,这意味着预处理器不会检查替换后的代码是否有效或合法。因此,如果宏定义不当或使用不当,可能会导致意外的结果或错误。

例:

#include <stdio.h>// 一个有问题的宏定义
#define SQUARE(x) x * xint main() {int a = 5;int result = SQUARE(a + 1); // 期望结果是(a+1)*(a+1),但实际结果是a+1*a+1printf("The square of (a + 1) is: %d
", result); // 输出结果是11,而不是36return 0;
}
  • 在这个例子中,由于宏SQUARE没有正确地用括号将参数包围起来,导致替换后的表达式变成了a + 1 * a + 1,而不是(a + 1) * (a + 1)。因此,输出结果不是期望的36,而是错误的11

为了避免这种问题,我们应该在定义宏时使用括号来保护参数和整个表达式:

#include <stdio.h>// 修改后的正确宏定义
#define SQUARE(x) ((x) * (x))int main() {int a = 5;int result = SQUARE(a + 1); // 现在结果是(a+1)*(a+1)printf("The square of (a + 1) is: %d
", result); // 输出结果是36return 0;
}

2.2 宏的作用域与生命周期
  • 宏定义在它们被声明的文件中是全局可见的,除非使用了特定的编译器选项或预处理指令来限制它们的可见性。此外,宏的生命周期贯穿整个编译过程,直到目标代码生成为止。一旦目标代码生成,宏就不再存在;它们只是编译过程中的一种辅助工具。

需要注意的是:

  • 由于宏是在预处理阶段进行替换的,因此它们不具有变量那样的作用域和生命周期概念。换句话说,宏在整个源文件中都是有效的,并且每次出现时都会被替换为其定义的内容。

2.3 宏与函数的区别

尽管宏在某些方面类似于函数(例如它们都可以接收参数并返回结果),但它们之间存在显著的差异:

  • 作用时机:宏在预处理阶段进行替换,而函数在运行时被调用。
  • 类型检查:函数在编译时会进行类型检查以确保参数的类型匹配,而宏则不进行任何类型检查。
  • 调试难度:由于宏是在预处理阶段展开的,因此在调试时可能难以跟踪和理解它们的实际行为。相比之下,函数具有明确的入口点和出口点,更容易进行调试和分析。
  • 性能考虑:虽然宏可以避免函数调用的开销(如栈操作和参数传递),但在某些情况下,过度使用宏可能会导致代码膨胀和性能下降。因此,在选择使用宏还是函数时需要根据具体情况进行权衡。

《3》高级宏技巧与应用案例

除了基本的宏定义之外,C语言还支持一些高级的宏技巧和应用场景。这些技巧和场景可以帮助我们编写更高效、更可维护的代码。

3.1 宏串联与字符串化

C语言提供了两个特殊的操作符来支持宏的字符串化和串联操作:###

  • #操作符用于将宏参数转换为字符串字面量,这在需要动态构建字符串时非常有用
#include <stdio.h>#define STRINGIFY(x) #x
int main() {printf("%s", STRINGIFY(Hello, World!)); // 输出"Hello, World!"return 0;
}
  • ##操作符用于连接两个标记(token)以形成一个新的标记。这在需要动态构建标识符名称时非常有用。
#include <stdio.h>#define CONCAT(a, b) int ## a ## _ ## b = a + b;CONCAT(x, y); // 展开为int

(2)文件包含

预处理的主要任务之一便是文件包含(File Inclusion),这一功能通过#include指令实现,使得一个源文件能够将另一个源文件的全部内容包含进来。


一、文件包含的基本概念
  • 文件包含允许开发者将一个或多个源文件的内容插入到当前正在编译的源文件中。这种机制极大地促进了代码的模块化和重用性。通过将常用的代码段、宏定义、函数声明等放在一个单独的头文件中,然后在需要的地方通过#include指令引入这些头文件,可以显著减少代码的重复,提高开发效率。

二、#include指令的使用方式

#include指令有两种基本的使用格式:

  1. 尖括号形式#include <文件名>
    这种形式通常用于包含标准库头文件或系统提供的头文件。预处理器会在系统的标准目录中寻找指定的文件。
  1. 双引号形式#include "文件名"
    这种形式则用于包含用户自定义的头文件。预处理器首先会在当前源文件所在的目录中查找指定的文件,如果找不到,再按照系统标准目录的路径进行查找。

三、文件包含的优势与注意事项
(1)优势
  • 模块化设计:通过文件包含,可以将程序划分为多个独立的模块,每个模块负责不同的功能,便于管理和维护。
  • 代码重用:将常用的代码段放在头文件中,可以在多个源文件中重复使用,避免代码冗余。
  • 易于调试和维护:当需要对某个功能进行修改时,只需修改相应的头文件即可,无需逐个修改包含该功能的源文件。
(2)注意事项
  • 防止重复包含:为了避免同一个头文件被多次包含导致的编译错误,通常会在头文件中使用条件编译指令(如#ifndef, #define, #endif)来确保头文件只被包含一次。
  • 路径问题:在使用双引号形式的#include指令时,需要注意指定正确的文件路径,否则会导致编译失败。
  • 依赖关系:如果文件A包含了文件B,而文件B又依赖于文件C,那么在文件A中需要先包含文件C,再包含文件B,以确保依赖关系的正确性。

四、示例说明

假设有一个名为math_utils.h的头文件,其中定义了几个数学运算的宏:

// math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))#endif // MATH_UTILS_H

然后,在一个源文件main.c中,可以通过以下方式包含这个头文件并使用其中的宏:

// main.c
#include <stdio.h>
#include "math_utils.h"int main() {int x = 5, y = 10;printf("Max: %d
", MAX(x, y));printf("Min: %d
", MIN(x, y));return 0;
}
  • 在这个例子中,main.c源文件通过#include "math_utils.h"指令包含了math_utils.h头文件,从而可以使用其中定义的MAXMIN宏来进行数学运算。

综上所述:

  • 文件包含是C语言预处理阶段的一个重要功能,它通过#include指令实现了代码的模块化和重用性,为开发者提供了极大的便利。

由于本文已经介绍很多了,所以小编在下一篇完结本节知识的介绍期待一下吧!!!!快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!

相关文章:

C语言预处理艺术:编译前的魔法之旅

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 本文目录 引言正文一、预处理的作用与流程&#xf…...

C++算法第十六天

本篇文章我们继续学习动态规划 第一题 题目链接 978. 最长湍流子数组 - 力扣&#xff08;LeetCode&#xff09; 题目解析 从上图可见其实有三个状态 代码原理 注意&#xff1a;我们在分析题目的时候分析出来的是三个状态&#xff0c;分别是上升、下降、平坦&#xff0c;但是…...

计算机网络 (45)动态主机配置协议DHCP

前言 计算机网络中的动态主机配置协议&#xff08;DHCP&#xff0c;Dynamic Host Configuration Protocol&#xff09;是一种网络管理协议&#xff0c;主要用于自动分配IP地址和其他网络配置参数给连接到网络的设备。 一、基本概念 定义&#xff1a;DHCP是一种网络协议&#xf…...

归子莫的科技周刊#2:白天搬砖,夜里读诗

归子莫的科技周刊#2&#xff1a;白天搬砖&#xff0c;夜里读诗 本周刊开源&#xff0c;欢迎投稿。 刊期&#xff1a;2025.1.5 - 2025.1.11。原文地址。 封面图 下班在深圳看到的夕阳&#xff0c;能遇到是一种偶然的机会&#xff0c;能拍下更是一种幸运。 白天搬砖&#xff0c;…...

平滑算法 效果比较

目录 高斯平滑 效果对比 移动平均效果比较: 高斯平滑 效果对比 右边两个参数是1.5 2 代码: smooth_demo.py import numpy as np import cv2 from scipy.ndimage import gaussian_filter1ddef gaussian_smooth_array(arr, sigma):smoothed_arr = gaussian_filter1d(arr, s…...

Elasticsearch容器启动报错:AccessDeniedException[/usr/share/elasticsearch/data/nodes];

AccessDeniedException 表明 Elasticsearch 容器无法访问或写入数据目录 /usr/share/elasticsearch/data/nodes。这是一个权限问题。 问题原因&#xff1a; 1、宿主机目录权限不足&#xff1a;映射到容器的数据目录 /data/es/data 在宿主机上可能没有足够的权限供容器访问。 …...

【Linux系统编程】——深入理解 GCC/G++ 编译过程及常用选项详解

文章目录 1. GCC/G 编译过程预处理&#xff08;Preprocessing&#xff09;编译&#xff08;Compilation&#xff09;汇编&#xff08;Assembly&#xff09;连接&#xff08;Linking&#xff09; 静态链接与动态链接静态链接动态链接静态库和动态库 GCC 常用选项关于编译器的周边…...

Mac安装配置使用nginx的一系列问题

brew安装nginx https://juejin.cn/post/6986190222241464350 使用brew安装nginx&#xff0c;如下命令所示&#xff1a; brew install nginx 如下图所示&#xff1a; 2.查看nginx的配置信息&#xff0c;如下命令&#xff1a; brew info nginxFrom:xxx 这样的&#xff0c;是n…...

Vue3中使用组合式API通过路由传值详解

在Vue 3中&#xff0c;使用组合式API来传递路由参数是一种常见的需求。Vue Router 是 Vue.js 的官方路由管理工具&#xff0c;可以在不同的场景下通过多种方式传递和接收路由参数。下面将详细讲解几种常见的路由传值方式&#xff0c;并提供相应的代码示例。 1. 通过路由参数传…...

两分钟解决 :![rejected] master -> master (fetch first) , 无法正常push到远端库

目录 分析问题的原因解决 分析问题的原因 在git push的时候莫名遇到这种情况 若你在git上修改了如README.md的文件。由于本地是没有README.md文件的&#xff0c;所以导致 远端仓库git和本地不同步。 将远端、本地进行合并就可以很好的解决这个问题 注意&#xff1a;直接git pu…...

浏览器安全(同源策略及浏览器沙箱)

一、同源策略&#xff08;Same Origin Policy&#xff09; 1.定义 同源策略&#xff08;Same - origin Policy&#xff09;是一种浏览器的安全机制。它规定一个网页的脚本只能访问和操作与它同源的资源。这里的 “源” 包括协议&#xff08;如 http、https&#xff09;、域名&…...

w~Transformer~合集11

我自己的原文哦~ https://blog.51cto.com/whaosoft/12472192 #LightSeq 最高加速9倍&#xff01;字节跳动开源8比特混合精度Transformer引擎,近年来&#xff0c;Transformer 已经成为了 NLP 和 CV 等领域的主流模型&#xff0c;但庞大的模型参数限制了它的高效训练和推理。…...

Coursera四门课备考入学考试

某学校入学考试复习用&#xff0c;刷到的话纯靠缘分&#xff0c;不方便回答多余问题 &#xff08;博主本人waive掉了没有考过&#xff0c;但还是基本都学完了&#xff09; 记录学习coursera的四门课&#xff08;顺序Py在DS前&#xff0c;其他无所谓&#xff09; Mathematics fo…...

Flink(八):DataStream API (五) Join

1. Window Join Window join 作用在两个流中有相同 key 且处于相同窗口的元素上。这些窗口可以通过 window assigner 定义&#xff0c;并且两个流中的元素都会被用于计算窗口的结果。两个流中的元素在组合之后&#xff0c;会被传递给用户定义的 JoinFunction 或 FlatJoinFunct…...

HarmonyOS NEXT边学边玩:从零实现一个影视App(六、视频播放页的实现)

在HarmonyOS NEXT中&#xff0c;ArkUI是一个非常强大的UI框架&#xff0c;能够帮助开发者快速构建出美观且功能丰富的用户界面。本文将详细介绍如何使用ArkUI实现一个影视App的视频播放页面。将从零开始&#xff0c;逐步构建一个功能完善的视频播放页面&#xff0c;并解释每一部…...

salesforce实现一个字段的默认初始值根据另一个字段的值来自动确定

在 Salesforce 中&#xff0c;可以通过 公式字段 或 触发器 (Trigger) 实现字段的默认初始值根据另一个字段的值来自动确定&#xff0c;具体实现方法如下&#xff1a; 1. 使用公式字段 公式字段是一种动态字段&#xff0c;值会根据公式实时计算。 步骤&#xff1a; 导航到字段…...

Linux 文件权限详解

目录 前言 查看文件权限 修改文件权限 符号方式 数字方式 前言 Linux 文件权限是系统中非常重要的概念之一&#xff0c;用于控制对文件和目录的访问。权限分为读&#xff08;Read&#xff09;、写&#xff08;Write&#xff09;、执行&#xff08;Execute&#xff09;三个…...

【混合开发】CefSharp+Vue桌面应用程序开发

为什么选择CefSharpVue做桌面应用程序 CefSharp 基于 Chromium Embedded Framework (CEF) &#xff0c;它可以将 Chromium 浏览器的功能嵌入到 .NET 应用程序中。通过 CefSharp&#xff0c;开发者可以在桌面应用程序中集成 Web 技术&#xff0c;包括 HTML、JavaScript、CSS 等…...

springBoot项目使用Elasticsearch教程

目录 一、引言&#xff08;一&#xff09;使用背景&#xff08;二&#xff09;版本库区别 二、引入依赖&#xff08;一&#xff09;springboot集成的es依赖&#xff08;建议&#xff09;&#xff08;二&#xff09;es提供的客户端库 三、配置&#xff08;以yaml文件为例&#x…...

模型 多元化思维(系统科学)

系列文章分享模型&#xff0c;了解更多&#x1f449; 模型_思维模型目录。融合多学科知识&#xff0c;全面解决问题。 1 多元化思维模型的应用 1.1 完美日记的私域流量运营 完美日记作为美妆行业的新兴品牌&#xff0c;通过多元化的思维模型在私域流量运营中取得了显著成功。…...

Google地图瓦片爬虫

地图地址说明 1、谷歌矢量(中文标注) http://mt{0-3}.google.cn/vt/vm416115521&hlzh-CN&glcn&x{x}&y{y}&z{z}&sGalileo 2、谷歌矢量(英文标注) http://mt{0-3}.google.cn/vt/vm416115521&hlen&glcn&x{x}&y{y}&z{z}&sGali…...

【C++】size_t全面解析与深入拓展

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;一、什么是size_t&#xff1f;为什么需要size_t&#xff1f; &#x1f4af;二、size_t的特性与用途1. size_t是无符号类型示例&#xff1a; 2. size_t的跨平台适应性示例对…...

Web端实时播放RTSP视频流(监控)

一、安装ffmpeg: 1、官网下载FFmpeg: Download FFmpeg 2、点击Windows图标,选第一个:Windows builds from gyan.dev 3、跳转到下载页面: 4、下载后放到合适的位置,不用安装,解压即可: 5、配置path 复制解压后的\bin路径,配置环境变量如图: <...

学习 Git 的工作原理,而不仅仅是命令

Git 是常用的去中心化源代码存储库。它是由 Linux 创建者 Linus Torvalds 创建的&#xff0c;用于管理 Linux 内核源代码。像 GitHub 这样的整个服务都是基于它的。因此&#xff0c;如果您想在 Linux 世界中进行编程或将 IBM 的 DevOps Services 与 Git 结合使用&#xff0c;那…...

C语言变长嵌套数组常量初始化定义技巧

有时候&#xff0c;我们需要在代码里配置一些常量结构&#xff0c;比如一个固定的动作流程ActionFlow&#xff1a;包含N&#xff08;即flow_num&#xff09;个动作列表&#xff08;ActionArray&#xff09;&#xff0c;每个动作列表包含M&#xff08;即act_num&#xff09;个可…...

如何查看特定版本的Spring源码

写在前面&#xff1a;大家好&#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正&#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是&#xff1a;https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油&#xff0c;冲鸭&#x…...

【深度学习】关键技术-激活函数(Activation Functions)

激活函数&#xff08;Activation Functions&#xff09; 激活函数是神经网络的重要组成部分&#xff0c;它的作用是将神经元的输入信号映射到输出信号&#xff0c;同时引入非线性特性&#xff0c;使神经网络能够处理复杂问题。以下是常见激活函数的种类、公式、图形特点及其应…...

网关相关知识

文章目录 什么是网关网关的主要作用网关的运用 什么是网关 网关又称网间连接器、协议转换器&#xff0c;也就是网段(局域网、广域网)关卡&#xff0c;不同网段中的主机不能直接通信&#xff0c;需要通过关卡才能进行互访&#xff0c;比如IP地址为192.168.31.9(子网掩码&#x…...

SpringBoot整合SpringSecurity详解

文章目录 SpringBoot整合SpringSecurity详解一、引言二、引入依赖三、配置 Spring Security四、自定义用户详细信息服务五、使用示例1. 创建用户实体类2. 测试登录功能 六、总结 SpringBoot整合SpringSecurity详解 一、引言 在当今的软件开发中&#xff0c;安全是一个至关重要…...

【C++基础】enum,union,uint8_t,static

enum 所以有时候使用 Enum 的目的&#xff0c;不是为了自定义一种数据类型&#xff0c;而是为了声明一组常量。 from: https://github.com/wangdoc/clang-tutorial/blob/main/docs/enum.md union C 语言提供了 Union 结构&#xff0c;用来自定义可以灵活变更的数据结构。它内部…...

怎样去同行网站做外连接/淘宝直通车推广怎么做

1. 合并数组array_merge()函数将数组合并到一起&#xff0c;返回一个联合的数组。所得到的数组以第一个输入数组参数开始&#xff0c;按后面数组参数出现的顺序依次迫加。示例代码&#xff1a;<?php $arr array("A","B","C");$brr array(&…...

wordpress 笑话主题/百度关键词搜索排名帝搜软件

夫妻之间是不可以形成雇佣关系的&#xff0c;通常情况下&#xff0c;夫妻之间存在共有关系&#xff0c;对婚姻关系存续期间获得的财产享有共同的处分权。关于夫妻之间是否能够形成雇佣关系的问题&#xff0c;合肥律师已经整理了如下的内容供大家做法律参考。 一、夫妻之间是否能…...

广州市公司网站建设品牌/常州seo博客

ioc&#xff0c;全称是Inversion of Control&#xff0c;字面理解叫控制反转。既然叫控制反转&#xff0c;那就是原来谁控制&#xff0c;后面转给了谁。 那着手点先从原来的“控制正转”切入&#xff0c;在oop中&#xff0c;操作的都是object基本上都是实例化、赋值属性、接口调…...

iis如何做网站/互联网广告销售是做什么的

1、下载solr &#xff1a;wget http://archive.apache.org/dist/lucene/solr/7.3.0/solr-7.3.0.tgz 或者去官网自己下&#xff1a;http://archive.apache.org/dist/lucene/solr/ 找下面图片字样点进去选版本2、解压solr 命令:tar -zxvf solr-7.3.0.tgz -C /usr/local/soft…...

东莞模块网站建设/seo导航

Node.js是一个基于Chrome JavaScript运行时建立的平台&#xff0c; 用于方便地搭建响应速度快、易于扩展的网络应用。Node.js 使用事件驱动&#xff0c; 非阻塞I/O 模型而得以轻量和高效&#xff0c;非常适合在分布式设备上运行的数据密集型的实时应用。 V8引擎执行Javascript的…...

wordpress米表域名展/十大教育培训机构排名

如何更改手机的开机画面&#xff1f; 1、刷一个合适的recovery刷机包 下载地址如下 http://www.clockworkmod.com/rommanager Boot Loader 是在操作系统内核运行之前运行的一段小程序。 所以不要轻易的碰&#xff0c;除非你是想手机成砖的。 危险命令 fastboot flash bootlo…...