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

指针(下)

文章目录

  • 指针(下)
  • 野指针、空指针
    • 野指针
    • 空指针
  • 二级指针
  • **main**函数的原型
    • 说明
  • 常量指针与指针常量
    • 常量指针
    • 指针常量
    • 常量指针常量
  • 动态内存分配
    • 常用函数
      • **malloc**
      • **calloc**
      • **realloc**
      • **free**
  • **void**与**void***的区别
  • 扩展:形式参数和实际参数的对应关系

指针(下)

野指针、空指针

野指针

  • 定义:访问了一个已经销毁或者访问受限的内存区域外的指针,这个指针就被称为野指针。

  • 野指针产生的场景:

    1. 变量未初始化,通过指针访问该变量

      int a;
      int *p = &a; // p就是野指针
      ptf(*p); // 访问野指针,但是数据不安全
      
    2. 指针变量未初始化

      int *p = NULL; // 此时的p也是野指针
      ptf(*p);
      
    3. 指针指向的内存空间被(free函数)回收了—后面讲

    4. 指针函数中直接返回了局部变量的地址。

    5. 指针指向数组以外的地址(下标越界)

  • 何避免野指针:

    写代码要养成两个习惯(通过编码规范避免)

  1. 指针变量幻及时初始化,如果暂时没有对应的值,建议赋值为NULL;
  2. 数组操作(遍历,指针运算)时,注意数组的长度,避免越界
  3. 指针指向的内存空间被回收,建议给这个指针变量赋值为NULL;
int *p = (int*)malloc(10);// 动态内存分配
free(p);// 动态内存释放
p = NULL;// p不指向任何空间
  1. 指针变量使用之前要检查它的有效性(以后开发中要做非空校验)

    int *p = NULL;
    if(!p)
    {
    return -1;
    }
    

    说明:NULL是空常量,它的值是0,这个NULL一般存放在内存中的0x00000000位置,这个地址只能存放NULL,不能被其他程序修改。

空指针

空指针,又被称作悬空指针:当一个指针的值是NULL,这个指针被称为空指针;对空指针访问会运行报错(段错误)

二级指针

  • 定义:二级指针,又被称作多重指针,引用一级指针的地址,此时这个指针变量就得定义成二级指针。
int a = 10;
int *p = &a;
int **w = &p;
  • 定义格式

数据类型 **变量名 = 指针数组的数组名或者一级指针的地址

// 指针数组
int array = {1,2,3};
int *arr = {&array[0],&array[1],&array[2]};// 指针数组
// 一级指针
int a = 10;
int *p = &a; // 一级指针
  • 举例:
// 字符型指针数组
char *arr[3] = {"abc","aaa034","12a12"};// 等效于:char arr[3][6] = {"abc","aaa034","12a12"}
// 定义二级指针并赋值(指针需要跟依赖的源同类型)
char **p = arr;// 正确
int array[2][3] = {{1,2,3},{11,22,33}};
int **k = array;// 编译报错,数据类型不相符(二维数组不等于指针数组)
int a = 90;
int *p = &a;// 一级指针
int **k = &p;// 正确,二级指针
  • 结论
  1. 二级指针和指针数组是等效,和二维数组不等效
  2. 二维数组和数组指针是等效,和二级指针不等效
  • 二级指针的用法:
  1. 如果是字符的二级指针,可以像遍历字符串数组一样遍历它
  2. 如果是其他的二级指针,就需要解引用两次访问它所指向的数据

案例:

/**
* 二级指针案例:使用指向指针数据的指针变量。
*/
#include <stdio.h>
void fun1(){char *name[]={"Follow me","BASIC","Great Wall","FORTRAN","Computer design"};// 定义一个二级指针char **p;// 定义循环变量int i = 0;// 遍历指针数组do{p = name + i;printf("%s\n",*p);i++;}while(i < 5);printf("\n");
}
void fun2()
{int arr1[5] = {11,12,13,14,15};// 创建一个指针数组int *arr[] = {&arr1[0],&arr1[1],&arr1[2],&arr1[3],&arr1[4]};int **p = arr,i = 0;// 遍历for(;i < 5; i++){// printf("%5d",**(p+i));printf("%5d",**p);p++;}printf("\n");
}
int main()
{fun1();fun2();
}

main函数的原型

定义:main函数有多种定义格式,main函数也是函数,函数相关的结论对main函数也有效(也可以定义main函数的函数指针)。

main函数的完整写法:

int main(int argc,char *argv[]){}
int main(int argc,char **argv){}

扩展写法:

int main(){}
int main(void){}
void main(){}
main(){} ---- int main(){}
void main(void){}
int main(int a){}
int main(int a,int b,int c){}
...

说明

  1. argc,argv是形参的名称,它们俩可以修改

  2. main函数的扩展写法有些编译器不支持,编译报警告

  3. argc和argv的常规写法:

    • argc:存储了参数的个数

    • argv:存储了所有参数的字符串形式

  4. main函数是系统通过函数指针的回调形式调用的

注意:如果一个函数没有写返回值类型,这个函数的默认返回类型是int。

案例:

/**
* main函数
*/
#include "stdio.h"
int main(int argc,char **argv)
{int k;for (k=1;k < argc;k++)printf("%s\n",argv[k]);
}

常量指针与指针常量

常量:分为字面量和只读常量,字面量(就是我们平时直接操作的如:

printf(12)|printf(“hello”));只读常量使用关键字 const 修饰,凡是被这个关键字修饰的变量,一旦赋值,值就不能改变。

语法:

// 字面量举例,字面量是一种匿名的常量
printf(12);
printf("请输入一个数:\n");// 只读常量
const int a = 10;
a = 21;// 编译错误,因为此时这个变量是只读常量,所以不可更改其值

常量指针

定义:常量的指针,本质是一个指针,指针指向的数据不能改变。

  • 定义格式:

    const 数据类型 *变量名;

    举例:

    const int *p; // p就是常量指针
    
  • 结论

    1. 常量指针指向的数据不能被改变(不能解引用间接修改数据)

    2. 常量指针的地址可以改变。

  • 应用场景:作为形式参数,实际参数需要给一个常量。

  • 案例:

#include <stdio.h>
/* 常量指针 */
void test1()
{// 定义变量int a = 10;// 定义常量指针const int *p = &a;// *p = 100; // 编译报错,常量的值不能修改(常量指针指向地址空间的数值不能修改)printf("%d\n",*p);// 10int b = 90;p = &b; // 编译通过,常量的地址可以修改(常量指针指向的地址空间可以发生改变)printf("%d\n",*p);// 90
}
int main()
{test1();
}

指针常量

  • 定义:指针的常量,指针的指向不能改变

  • 定义格式

    数据类型* const 变量名;

举例:

int* const p; // 指针常量 1
  • 结论:

    1. 指针常量的指向不能被改变(不能给指针变量重新赋地址值)

    2. 指针常量指向的数据可以改变。

  • 注意:指针常量在定义时就要赋值;不能先定义后赋值,否则编译报错。

  • 案例:

    /**
    * 常量指针与指针常量
    */
    #include <stdio.h>
    /* 指针常量 */
    void test2()
    {// 定义变量int a = 10;// 定义指针变量int* const p = &a;// 错误写法:先定义,后赋值(编译报错)// int* const p;// p = &a;// 间接取数据pirntf("%d\n",*p);// int b = 200;// p = &b;// 编译报错,地址不能改变*p = 200;printf("%d\n",*p);// 200
    }
    int main()
    {test2();
    }
    

常量指针常量

  • 定义语法:

    const 数据类型* const 变量名;

  • 举例:

const int* const p; // 常量指针常量
  • 作用:p的指向不能被改动(地址),p指向的数据不能被改(地址对应内存中存放的数据)

动态内存分配

我们要想实现动态内存分配,就需要学习标准C提供的函数库:

  1. 函数所属的库文件
  2. 函数的原型-函数的声明
    • 函数名
    • 形参
    • 返回值类型
  3. 函数的功能

注意:内存分配函数在申请内存时,建议用多少申请多少,可以有少量的预留量;但不能越界访问(虽然编译和运行不报错,但数据不安全)

常用函数

malloc

  • 头文件: #include <stdlib.h>

  • 函数功能:C 库函数 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。

  • 函数原型:

    • 函数名:malloc

    • 形式参数:size_t size:内存块的大小,以字节为单位。本质上就是一个 unsigned int

    • 返回值类型:void* :该函数返回一个指针,指向已分配大小的内存,如果请求失败,返回NULL。

  • 举例:

    int *p = (int*)malloc(4);
    
  • 说明:

    1. malloc函数分配的内存没有默认值,是不确定数,大概率是0;
    2. malloc函数申请的内存空间连续。

calloc

  • 头文件: #include <stdlib.h>
  • 函数功能:C库函数 void * calloc(size_t nitems,size_t size) 分配所需的内存空间,并返回一个指向它的指针。

malloc和calloc之间不同点事,malloc不会设置内存为零,而calloc会设置内存为零。

  • 函数原型: void *calloc(size_t nitems,size_t size)

  • 函数名:calloc

  • 形式参数:

    • size_t nitems:申请多少个
    • size_t size:一个占几个内存单元(一个内存单元 等于 一个字节)
  • 返回值类型:void*:该函数返回一个指针,指向已分配大小的内存。如果请求失败,返回NULL。

  • 举例:

    int *p = (int*)calloc(3,4); // p指向的空间的大小是12个字节
    if(!p) printf("内存申请失败!\n");
    
  • 说明:

    1. calloc函数分配的内存有默认值,每个内存单元都是0
    2. calloc函数申请的内存空间连续
    3. calloc大多时候为数组中的元素申请内存

    转存栈中数组中的数据:

    int arr[3] = {10,20,30}; // 在栈区
    int *p = (int*)calloc(3,4); // 申请内存,在堆区
    if(!p) puts("内存申请失败!");
    // 转存
    for(int i = 0;i < 3; i++)p[i] = arr[i];// 遍历
    for(int i = 0;i < 3; i++)printf("%d,",p[i]);
    printf("\n");// p使用完,记得释放内存
    free(p);
    p = NULL; // 内存回收后,建议置空
    

realloc

  • 头文件: #include <stdlib.h>

  • 函数功能:尝试重新调整之前调用malloc或calloc所分配的ptr所指向的内存块的大小。

  • 函数原型: void *realloc(void *ptr,size_t size)

  • 函数名:realloc

  • 形式参数:

    • void *ptr:是malloc或者calloc的返回值
    • size_t size:重新分配后的内存大小
  • 返回值:void*:该函数返回一个指针,指向已分配大小的内存。如果请求失败,返回NULL。

  • 案例

    int *p = (int*)malloc(4);
    int *w = (int*)realloc(p,20);
    // int *q = (int*)realloc(p,0); // 等效于free(p)
    

    说明:

    1. realloc以原来malloc返回的内存地址开始,分配总共20个字节的内存空间

    2. 如果原来的内存空间后有20个连续空间,就扩容20-4 =16个内存单元,返回原来旧的内存首地址。

    3. 如果原来的内存空间后不够20个连续内存空间,就重新找一个内存地址开始,申请20个内存单元。并将原来的数据拷贝到新的内存中,回收旧的内存单元,并返回新的内存首地址。

free

  • 头文件: #include <stdlib.h>

  • 函数功能:释放之前调用 malloc、calloc、realloc所分配的内存空间,是访问完记得使用NULL置空。

  • 函数原型: void free(void *ptr)

    • 函数名:free
  • 形式参数:

    • void *ptr:calloc,malloc.realloc的返回值
  • 返回值类型:void:没有返回值

  • 注意:

    1. 堆内存中的指针才需要回收,栈中系统会自动回收

    2. 堆内存不能重复回收,运行会报错

说明:

  1. 堆的内存空间相比较栈要大很多
  2. 内存分配函数返回的指针变量可以参与运算(只读),但不能被修改(p++或者p+=i 是错误的)

voidvoid*的区别

  • 定义:

    • void:是空类型,是数据类型的一种
    • void*:是指针类型,是指针类型的一种,可以匹配任意类型的指针,类似于通配符
  • void

    • 说明:void作为返回值类型使用,表示没有返回值;作为形参,表示形参列表为空,在调用函数是不能给实参

    • 举例

      // 函数声明
      void fun(void); // 等效于 void fun();
      // 函数调用
      fun();
      
  • void*

    • 说明:

      • void*是一个指针类型,但该指针的数据类型不明确,无法通过解引用获取 内存中的数据,因为 void* 不知道访问几个内存单元。

      • void*是一种数据类型,可以作为函数返回值类型,也可以作为形参类型

      • void*类型的变量在使用之前必须强制类型转换,明确它能够访问几个字节的内存空间

        int *p = (int*)malloc(4);
        double *p2 = (double*)malloc(8);
        

        举例:

        #include <stdio.h>
        #include <stdlib.h>
        // 函数定义
        void* fun(void* p) // 指针函数(返回值类型是指针的函数,此时返回的是不明确类型,需要外部强转)
        {int *p;// double *p;// long *p;// char *p;return p;
        }
        // 函数调用
        void main()
        {int *p;void* a = fun(p);// 这种接收方式,实际上没有意义printf("%p\n",a);// 可以正常打印,打印出一个地址*a = 10;// 编译报错,void*变量不能解引用访问数据int *w = (int*)a;*w = 10;// 编译和运行正常,void*变量a在使用前已经强制类型转换了,数据类型明确了,访问的内存单元明确了。
        }
        
      • 说明:

        1. void作为返回值类型:这个函数可以返回任意类型( char,int*,double*等 )的指针。
        2. void作为形参类型:这个函数在调用时,可以给任意类型( char,int*,double*等 )的指针。
      • 总结:

        • void* 类似于通配符,不能对void*类型的变量解引用(因为不明确内存单元的大小)。
        • void*在间接访问(解引用)前要强制类型转换,但不能太随意,否则存和去的数据类型不一致。

扩展:形式参数和实际参数的对应关系

//形式参数和实际参数的对应关系
#include <stdio.h>
//void test(int arr[]) //可以
//void test(int arr[2]) //可以
//void test(int * arr) //可以
//void test(int *arr[]) //不可以,编译报错
//void test(int ** arr) //不可以
//void test(int (*arr)[]) //不可以
//---------------------------------
//void test2(int * arr[]) //可以
//void test2(int ** arr) //可以
void test2(int (*arr)[]) //不可以
{printf("test执行了\n");
}
int main()
{
/*int arr[3]={0};test(arr);*/int *arr[3] = {0};test2(arr);return 0;
}
//形式参数和实际参数的对应关系
#include <stdio.h>
//void test(int arr[2][3]) //可以
//void test(int arr[][3]) //可以
//void test(int arr[2][]) //不可以
//void test(int arr[][]) //不可以
//void test(int (*arr)[]) //可以
//void test(int(*)arr[]) //语法错误
//void test(int(*arr)[3])
//void test(int *arr[]) //不可以
//----------------------------------------
//void test2(int *arr[]) //可以
//void test2(int arr[][1]) //不可以
//void test2(int **arr) //可以
void test2(int(*arr)[]) //不可以
{printf("test\n");
}
int main()
{/*int arr[2][3] = {0};test(arr);*//*int a = 20;int *arr[] = {&a};test2(arr);*/int** p;test3(p);return 0;
}

相关文章:

指针(下)

文章目录 指针(下)野指针、空指针野指针空指针 二级指针**main**函数的原型说明 常量指针与指针常量常量指针指针常量常量指针常量 动态内存分配常用函数**malloc****calloc****realloc****free** **void**与**void***的区别扩展&#xff1a;形式参数和实际参数的对应关系 指针…...

C# 浅谈IEnumerable

一、IEnumerable 简介 IEnumerable 是一个接口&#xff0c;它定义了对集合进行迭代所需的方法。IEnumerable 接口主要用于允许开发者使用foreach循环来遍历集合中的元素。这个接口定义了一个名为 GetEnumerator 的方法&#xff0c;该方法返回一个实现了 IEnumerator 接口的对象…...

mmdebstrap:创建 Debian 系统 chroot 环境的利器 ️

文章目录 mmdebstrap 的一般性参数说明 &#x1f4dc;mmdebstrap 的常见用法示例 &#x1f308;使用 mmdebstrap 的注意事项 ⚠️ &#x1f308;你好呀&#xff01;我是 山顶风景独好 &#x1f388;欢迎踏入我的博客世界&#xff0c;能与您在此邂逅&#xff0c;真是缘分使然&am…...

【Linux SQLite数据库】一、SQLite交叉编译与移植

SQLite 是一个用 C 语言编写的开源、轻量级、快速、独立且高可靠性的 SQL 数据库引擎&#xff0c;它提供了功能齐全的数据库解决方案。SQLite 几乎可以在所有的手机和计算机上运行&#xff0c;它被嵌入到无数人每天都在使用的众多应用程序中。此外&#xff0c;SQLite 还具有稳定…...

每天写两道(数组篇)移除元素、

27.移除元素 给你一个数组 nums 和一个值 val&#xff0c;你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。 假设 nums 中不等于 val 的元素数量为 k&#xff0c;要通过此题&#xff0c;您需要执行以下操作&#…...

Unity 使用 NewtonSoft Json插件报错

JsonReaderException: Unexpected character encountered while parsing value: . Path , line 0, position 0. 通过断点发现&#xff0c;头有一串ZWNBSP&#xff0c;这个是BOM格式的JSON。在文件下看不到。 解决方法&#xff1a;改编码格式&#xff0c;Remove BOM....

k8s 部署 Mysqld_exporter 以及添加告警规则

最近监控 mysql 数据库&#xff0c;用了 pmm-server、pmm-client 发现监控是真的不太好用&#xff0c;还是用回 prometheus 吧。 部署mysqld_exporter k8s 部署最新版本的 mysqld_exporter&#xff0c;支持的数据库版本 MySQL >5.6、MariaDB > 10.3。 先在数据库创建用…...

基于STM32开发的智能农业环境监测系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 初始化代码控制代码应用场景 农田环境监测温室环境控制常见问题及解决方案 常见问题解决方案结论 1. 引言 智能农业环境监测系统通过集成多种环境传感器&#xff0c;实时监测土壤湿度、温度…...

【SQL】平均售价

目录 题目 分析 代码 题目 表&#xff1a;Prices ------------------------ | Column Name | Type | ------------------------ | product_id | int | | start_date | date | | end_date | date | | price | int | ---------------…...

存储器与CPU的连接

1.单块存储芯片与CPU的连接 单独的一块独立的存储芯片提供的线有&#xff1a;地址总线&#xff0c;数据总线&#xff0c;读写控制线&#xff0c;片选线&#xff0c;如果该存储器只有八根数据总线用于输出数据&#xff0c;而cpu一次可以读64位的数据呢&#xff1f; 我们可以将八…...

unity--webgl 访问本地index.html

目录 1:使用本地服务器 1.1 使用 Python 的 SimpleHTTPServer 1.2 使用 Node.js 的 http-server 2&#xff1a;让其他人通过 IP 地址来访问你的 Unity WebGL 项目 2.1: 确保服务器可访问 2.2 获取公共 IP 地址 2.3 配置本地服务器 1.使用 Python 的 SimpleHTTPServer 2…...

慢慢欣赏DPDK RTE_MAX_ETHPORTS的定义

DPDK代码里面&#xff0c;RTE_MAX_ETHPORTS是一个常见的宏定义&#xff0c;但是在.c和.h文件找不到其定义&#xff0c;在全文件搜索条件下&#xff0c;在config/meson.build找到这么一个定义 dpdk_conf.set(RTE_MAX_ETHPORTS, get_option(max_ethports)) 该宏定义是根据构建输…...

Java Nacos与Gateway的使用

Java系列文章目录 IDEA使用指南 Java泛型总结&#xff08;快速上手详解&#xff09; Java Lambda表达式总结&#xff08;快速上手详解&#xff09; Java Optional容器总结&#xff08;快速上手图解&#xff09; Java 自定义注解笔记总结&#xff08;油管&#xff09; Jav…...

前端项目中的Server-sent Events(SSE)项目实践及其与websocket的区别

前端项目中的Server-sent Events(SSE)项目实践 前言 在前端开发中&#xff0c;实时数据更新是提升用户体验的重要因素之一。Server-SentEvents(SSE)是一种高效的技术&#xff0c;允许服务器通过单向连接将实时数据推送到客户端。下面将从SSE的基本改变&#xff0c;使用场景展…...

《老俞闲话|唯爱和热情不可辜负》读后感

《老俞闲话&#xff5c;唯爱和热情不可辜负》读后感 俞敏洪先生的这篇讲话充满了深情与智慧&#xff0c;他以自己丰富的人生经历和教育实践&#xff0c;向我们展现了一位教育家对于教育事业的热爱和对教师角色的深刻理解。 情感真挚&#xff0c;触动人心 俞敏洪先生的讲话中流…...

C语言 ——— 在杨氏矩阵中查找具体的某个数

目录 何为杨氏矩阵 题目要求 代码实现 何为杨氏矩阵 可以把杨氏矩阵理解为一个二维数组&#xff0c;这个二维数组中的每一行从左到右是递增的&#xff0c;每一列从上到下是递增的 题目要求 在杨氏矩阵中查找具体的某个数 要求&#xff1a;时间复杂度小于O(N) 代码实现…...

DAI-Net: 基于对偶自适应交互网络的药物推荐算法

引言 DAI-Net: Dual Adaptive Interaction Network for Coordinated Medication Recommendation 论文链接&#xff1a;https://ieeexplore.ieee.org/document/10614809 代码链接&#xff1a;GitHub - obananas/DAI-Net 在现代医疗保健中&#xff0c;如何利用电子健康记录&a…...

haproxy高级功能及配置

章节 一、haproxy 基础用法 二、haproxy 高级用法 三、haproxy之ACL的使用 目录 1 基于cookie的会话保持 1.1 cookie命名&#xff0c;并赋予其值 1.2 验证cookie信息 1.2.1 Windows浏览器验证 1.2.2 Linux下虚拟机验证 2 IP透传 2.1 四层与七层透传的区别 2.2 七层IP透传 2.2…...

【前端】NodeJS:记账本案例优化(MongoDB数据库)

文章目录 1 字符串转为时间对象——Moment2 记账本实例优化 1 字符串转为时间对象——Moment Moment.js中文网&#xff1a;https://momentjs.cn/docs/#/parsing/。 npm install moment // 安装moment var moment require(moment); // require moment().format(); 2 记账本实…...

Padding Mask;Sequence Mask;为什么如果没有适当的掩码机制,解码器在生成某个位置的输出时,可能会“看到”并错误地利用该位置之后的信息

目录 掩码Mask Padding Mask Sequence Mask 为什么需要Sequence Mask? Sequence Mask是如何工作的? 具体实现 为什么如果没有适当的掩码机制,解码器在生成某个位置的输出时,可能会“看到”并错误地利用该位置之后的信息 自回归性质 一、定义 二、性质 三、应用限制…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

如何配置一个sql server使得其它用户可以通过excel odbc获取数据

要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据&#xff0c;你需要完成以下配置步骤&#xff1a; ✅ 一、在 SQL Server 端配置&#xff08;服务器设置&#xff09; 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到&#xff1a;SQL Server 网络配…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...

Java数组Arrays操作全攻略

Arrays类的概述 Java中的Arrays类位于java.util包中&#xff0c;提供了一系列静态方法用于操作数组&#xff08;如排序、搜索、填充、比较等&#xff09;。这些方法适用于基本类型数组和对象数组。 常用成员方法及代码示例 排序&#xff08;sort&#xff09; 对数组进行升序…...