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

C语言中的基础指针操作

在C语言中,指针是一个非常重要的概念,它提供了直接访问内存地址的能力。指针变量用于存储内存地址,而不是数据值,在某种意义上和门牌号具有相似含义:指针是一个变量,其存储的是另一个变量的内存地址,这个内存地址唯一的标识,用于指向特定的内存位置。门牌号也是用来唯一标识一个具体的房屋或地址的,但指针的使用要复杂得多,涉及到内存的管理、指针的运算、野指针的避免等多个方面。在处理数组、字符串、动态内存分配以及函数参数传递等方面使得程序员们能够编写出更灵活、更高效的代码。

指针的概念

指针是一个变量,其值为另一个变量的地址,即直接指向内存中的某个位置,指针的声明需要在变量类型前加上星号*,像int *ptr;就声明了一个指向整数的指针变量ptr

指针的用途和功能

  1. 动态内存管理:C语言允许程序员在运行时动态地分配和释放内存,通过指针来实现,如使用malloccallocrealloc等函数分配内存,使用free函数释放内存。

  2. 数组操作:指针可以用来遍历数组,因为数组名本质上是一个指向数组首元素的指针。使用指针进行数组操作比使用数组索引更加高效。

  3. 字符串处理:在C语言中字符串是通过字符数组实现的。因此,字符串操作(如复制、拼接等)可以通过指针操作来实现。

  4. 函数参数传递:通过使用指针作为函数参数,可以在函数内部修改外部变量的值,实现数据的双向传递。

  5. 指向函数的指针:指针也可以指向函数,这使得可以将函数作为参数传递给其他函数,或者通过指针调用函数。

  6. 指向指针的指针:C语言允许创建指向指针的指针,这在进行复杂数据结构(如链表、树等)的操作时非常有用。

指针操作的大概流程如下
在这里插入图片描述

指针的基础操作

声明并初始化指针

在定义指针前需要先声明一个整数变量(我定义的value)并初始化,随后声明一个指向整数的指针变量(我声明的是pointer,很多人习惯使用p)并初始化为value的地址

    int value = 10; int * pointer = &value;

在C语言中这里的三种写法都是可以的:

int* pointer = &value;
int * pointer = &value;
int *pointer = &value;

随后即可通过访问指针来查询这个整型变量(value)的值:

 printf("通过指针访问的值: %d \n", *pointer); 

完整代码如下:

#include <stdio.h>  int main() {  int value = 10; int *pointer = &value; printf("通过指针访问的值: %d\n", *pointer);  return 0;
}

输出内容:通过指针访问的值: 10

修改指针指向的值

在C语言中,如果已经声明并初始化了一个指针,可以做到只修改指针所指向的值,原变量的数值不会改变。就好比结婚一样,老实的Java程序员大锤和小美去民政局登记结婚(为一个变量声明并初始化了一个指针),但大锤满足不了小美了(原数值因为各种原因在某项功能中需要进行改动),小美又不想离婚(修改原变量值),于是小美就找到了老王来满足她(修改指针所指向的值),以后小美还可以找老陈、老宋、老李(多次修改指针所指向的值),但是这样会造成:1.大锤没法活了(程序崩溃),2.孩子不是大锤亲生(野指针),3.家丑外扬(内存泄漏),4.小美被玩坏了(数据损坏)。根据刚才的代码继续编写:

#include <stdio.h>  int main() {  int value = 10; int *pointer = &value; printf("通过指针访问的值: %d\n", *pointer);  // 修改指针指向的值  *pointer = 20;  printf("修改后通过指针访问的值: %d\n", *pointer);  printf("直接访问变量value的值: %d\n", value);  return 0;  
}

输出内容可以看出,指针所指向的值发生了更改,而原变量的值未发生任何变化:
在这里插入图片描述

取地址和解引用操作

在C语言中取地址操作是将变量的地址赋值给指针,而解引用操作则是通过指针访问它所指向的变量的值。这两个操作在C语言的指针使用中非常重要,它们允许我们通过指针间接地访问和操作内存中的数据。

修改一下之前的代码,通过&运算符将value的地址赋给了pointer,进行了取地址操作

#include <stdio.h>  int main() {  int value = 20;    int *pointer;        // 在指针变量中存储value的地址,即取地址操作  pointer = &value;      printf("value变量的地址: %p\n", &value);  printf("通过pointer指针访问value变量的值: %d\n", *pointer);  return 0;  
}

输出中的0x7ffdee0e6ddc是变量value在内存中的地址,内存地址是操作系统分配给程序用于存储数据的物理或虚拟内存位置,每个程序运行时,操作系统都会为其分配一块内存空间,程序中的变量就存储在这块空间的特定地址上,同时每次程序运行时,操作系统可能会分配不同的内存地址给程序中的变量,0x7ffdee0e6ddc这个地址只是在这次运行程序时有效,下次运行时可能会有所不同。
在这里插入图片描述

指针的算术运算

指针的算术运算分为指针加减运算和指针相减运算
指针加减运算:指针可以进行加减运算,其结果是指针向前或向后移动若干个元素的距离(不是字节),移动的字节数取决于指针指向的数据类型。
指针相减运算:两个指针相减的结果是两个指针之间相隔的元素个数,要求两个指针指向同一块内存区域。
以下代码定义了两个数组:一个short类型的dataset数组和一个double类型的bills数组,每个数组都有SIZE 4个元素。然后,它定义了两个指针变量ptiptf,分别指向这两个数组的起始位置,随后代码进入一个循环,遍历这两个数组。在每次迭代中,它都会计算并打印出ptiptf指针在加上index值后的地址。这里pti + indexptf + index分别表示ptiptf指针向前移动indexshortdouble元素的位置。由于指针的加减运算是以它指向的数据类型的大小为单位进行的,所以pti每次增加2个字节(因为short类型通常占2个字节),而ptf每次增加8个字节(因为double类型通常占8个字节)。在打印指针地址时,代码将指针转换为void*类型。这是因为printf函数使用%p格式说明符来打印指针,而%p期望一个void*类型的参数。将指针转换为void*类型可以确保无论指针指向什么类型的数据,都能以统一的方式打印其地址。

#include <stdio.h>  #define SIZE 4  int main()  
{  short dataset[SIZE];  short *pti;  short index;  double bills[SIZE];  double *ptf;  pti = dataset;  ptf = bills;  printf("%23s %15s\n", "short pointers", "double pointers");  for (index = 0; index < SIZE; index++)  {  printf("pointers + %d: %10p %10p\n", index, (void*)(pti + index), (void*)(ptf + index));    }  return 0;  
}

代码会在终端输出以下内容:

                  short          double
pointers + 0: 0x7ffc8b926ef8 0x7ffc8b926f00 
pointers + 1: 0x7ffc8b926efc 0x7ffc8b926f10 
pointers + 2: 0x7ffc8b926f00 0x7ffc8b926f20 
pointers + 3: 0x7ffc8b926f04 0x7ffc8b926f30 
指针的比较

在C语言中可以使用关系运算符(如==、<、>等)来比较两个指针,比较的是它们所指向的地址的大小。
这里定义了一个长度为10的数组array,随后声明了三个指针ptr1、ptr2、ptr3,ptr1指向array的第3个元素 ,ptr2指向array的第6个元素 ,ptr3ptr1指向相同的地址:

#include <stdio.h>  int main() {  int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};  int *ptr1, *ptr2, *ptr3;  ptr1 = &array[2]; // ptr1指向array的第3个元素  ptr2 = &array[5]; // ptr2指向array的第6个元素  ptr3 = ptr1;      // ptr3与ptr1指向相同的地址  // 比较ptr1和ptr2  if (ptr1 < ptr2) {  printf("ptr1 < ptr2\n");  } else {  printf("ptr1 >= ptr2\n");  }  // 比较ptr1和ptr3  if (ptr1 == ptr3) {  printf("ptr1 == ptr3\n");  } else {  printf("ptr1 != ptr3\n");  }  // 比较ptr2和ptr1  if (ptr2 > ptr1) {  printf("ptr2 > ptr1\n");  } else {  printf("ptr2 <= ptr1\n");  }  return 0;  
}

代码运行后再终端输出:

ptr1 < ptr2
ptr1 == ptr3
ptr2 > ptr1
指针与数组

在C语言中,数组名可以视为指向数组首元素的指针,因此可以使用指针来遍历数组元素,可以使用指针算术运算来访问数组中的元素。
以下代码中的dqys不仅代表了一个包含12个整数的数组,同时也可以被看作是一个指向int类型的指针,它指向dqys数组的第一个元素,在随后的for循环中使用了指针算术运算来遍历数组dqys。表达式dqys + index表示指针dqys向前移动indexint类型元素的位置。因为dqys是一个指向int的指针,所以每次递增都会使指针地址增加sizeof(int)个字节。通过解引用操作符*可以获取该地址处的值,即数组dqys中索引为index的元素的值。当index为0时,*(dqys + 0)就相当于dqys[0],它表示数组的第一个元素,其值为31。同理,*(dqys + 1)则相当于dqys[1],它表示数组的第二个元素,其值为28:

#include <stdio.h>#define MONTHS 12int main()
{int dqys[MONTHS] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int index;for (index = 0; index < MONTHS; index++){printf("%2d 月有 %d 天. \n", index + 1, *(dqys + index));}return 0;
}

代码输出内容如下:

 1 月有 31 天. 2 月有 28 天. 3 月有 31 天. 4 月有 30 天. 5 月有 31 天. 6 月有 30 天. 7 月有 31 天. 8 月有 31 天. 9 月有 30 天. 
10 月有 31 天. 
11 月有 30 天. 
12 月有 31 天. 
指针与函数

C语言中允许指针指向函数,这使得可以将函数作为参数传递给其他函数,或者通过指针调用函数,同时也可以通过将指针作为函数参数传递,可以在函数内部修改外部变量的值。
这里的modifyValue函数接收一个int类型的指针作为参数,并通过该指针修改外部变量的值。add函数用来返回两个整数的和。executeFunction函数接收一个函数指针作为参数,并通过该函数指针调用函数。随后在main函数中,首先使用modifyValue函数通过指针修改外部变量的值。然后声明了一个函数指针functionPointer,并将其指向add函数。最后将该函数指针作为参数传递给executeFunction函数,并通过该函数指针调用add函数。

#include <stdio.h>  // 定义一个函数,该函数接收一个int类型的指针作为参数  
void modifyValue(int *value) {  //函数接收一个int类型的指针作为参数*value = 10; // 通过指针修改外部变量的值  
}  int add(int a, int b) {  // 函数用来返回两个整数的和 return a + b;  
}  void executeFunction(int (*func)(int, int), int a, int b) {  // 接收一个函数指针作为参数,并调用该函数int result = func(a, b); // 通过函数指针调用函数  printf("结果为: %d\n", result);  
}  int main() {  int variable = 0;  printf("数值修改后: %d\n", variable);  modifyValue(&variable); // 将变量的地址传递给函数以修改其值  printf("数值修改前: %d\n", variable);  // 使用函数指针调用函数  int (*functionPointer)(int, int) = add; // 声明一个函数指针,并将其指向add函数  executeFunction(functionPointer, 5, 3); // 将函数指针作为参数传递给executeFunction函数  return 0;  
}
动态内存分配

在C语言中提供了mallocfree函数用于动态内存分配和释放。malloc函数用于分配指定大小的内存空间,并返回一个指向该空间的指针;free函数用于释放已分配的内存空间。
下面代码中先声明了一个int类型的指针ptr,并将其初始化为NULL。然后使用malloc函数动态分配了足够存储5个整数的内存空间,并将返回的指针赋值给ptr。随后使用指针算术运算访问和修改动态分配的内存空间中的内容。之后使用for循环打印出动态分配的内存空间中的内容。最后使用free函数释放了已分配的内存空间,并将ptr重新设置为NULL避免空指针。

#include <stdio.h>  
#include <stdlib.h>  int main() {  int *ptr = NULL; // 声明一个int类型的指针,并初始化为NULL  int n = 5; // 存储5个整数  ptr = (int*)malloc(n * sizeof(int)); // 使用malloc函数动态分配内存空间,分配了n个int大小的内存空间,并将返回的指针转换为int类型的指针  // 检查malloc函数是否成功分配了内存,如果内存分配失败就退出程序 if (ptr == NULL) {  printf("内存分配GG了\n");  return 1; }  // 使用指针访问和修改动态分配的内存空间中的内容,通过指针算术运算访问数组元素,并赋值    for (int i = 0; i < n; i++) {  *(ptr + i) = i + 1; }  // 通过指针算术运算访问数组元素,并打印动态分配的内存空间中的内容  for (int i = 0; i < n; i++) {  printf("%d ", *(ptr + i));   }  printf("\n");  // 使用free函数释放ptr指向的内存空间   free(ptr); ptr = NULL; // 释放内存后,ptr变成了悬空指针,建议将ptr重新设置为NULL以避免悬空指针的问题  return 0;  
}
多级指针、指针数组、const指针、void指针

在C语言中出了基础的指针,以下的几种指针方式也很常见
多级指针:指向指针的指针,用于实现更复杂的数据结构和操作,如动态内存分配中的二维数组。
指针数组:数组中的元素是指针类型,常用于存储多个字符串或指向函数的指针。
const指针:指向常量的指针或指针常量,用于限制指针的指向或指针所指向的值不可修改。
void指针:通用指针类型,可以指向任意类型的数据,但在使用前通常需要类型转换。

#include <stdio.h>  
#include <stdlib.h>  int main() {  // 多级指针,指向指针的指针  int value = 10;  int *ptr1 = &value;  int **ptr2 = &ptr1; int ***ptr3 = &ptr2; int ****ptr4 = &ptr3;int *****ptr5 = &ptr4;int ******ptr6 = &ptr5;int *******ptr7 = &ptr6;printf("通过多级指针访问值:%d\n", *******ptr7);  // 存储字符串  char *strings[] = {"Hello", "Gayboy", "GGBond"};  int i;  for (i = 0; i < 3; i++) {  printf("指针数组中的字符串:%s\n", strings[i]);  }  const int constValue = 20;  const int *constPtr = &constValue;  // *constPtr = 30; 不能修改指向常量的指针所指向的值  printf("指向常量的指针:%d\n", *constPtr);  // 指针常量int anotherValue = 30;  int *const constPtr2 = &anotherValue;  // constPtr2 = &value; 这样就是错误的,指针常量的值不可修改  *constPtr2 = 40; printf("指针常量的指向值:%d\n", *constPtr2);  // 最后设一个通用指针  int intValue = 50;  float floatValue = 3.14f;  void *voidPtr;  voidPtr = &intValue;  printf("通过void指针访问int值:%d\n", *(int *)voidPtr);  voidPtr = &floatValue;  printf("通过void指针访问float值:%f\n", *(float *)voidPtr);  return 0;  
}

运行结果如下:
在这里插入图片描述

相关文章:

C语言中的基础指针操作

在C语言中&#xff0c;指针是一个非常重要的概念&#xff0c;它提供了直接访问内存地址的能力。指针变量用于存储内存地址&#xff0c;而不是数据值&#xff0c;在某种意义上和门牌号具有相似含义&#xff1a;指针是一个变量&#xff0c;其存储的是另一个变量的内存地址&#x…...

LabVIEW环境下OCR文字识别的实现策略与挑战解析

引言 在自动化测试领域&#xff0c;OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;技术扮演着重要角色&#xff0c;它能够将图像中的文字转换成机器可编辑的格式。对于使用LabVIEW约5个月&#xff0c;主要进行仪器控制与数据采集的你而言…...

中英双语介绍美国的州:堪萨斯州(Kansas)

中文版 堪萨斯州简介 堪萨斯州&#xff08;Kansas&#xff09;位于美国中部&#xff0c;以其广阔的平原、丰富的农业资源和多样的文化遗产而著称。以下是对堪萨斯州的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化和主要城市。 地理位置 堪萨斯州位于美国中…...

信息收集---端口服务信息收集

1. 什么是端口 是设备与外界通讯交流的出口。端口可分为虚拟端口和物理端口&#xff0c;其中虚拟端口指计算机内部或交换机路由器内的端口&#xff0c;不可见。例如计算机中的80端口、21端口、23端口等。物理端口又称为接口&#xff0c;是可见端口&#xff0c;计算机背板的RJ45…...

Python知识点背诵手册,超详细知识梳理

一、手册介绍 《Python知识点背诵手册》是一份详尽的Python学习资料&#xff0c;旨在帮助学习者系统地掌握Python语言的基础知识和进阶技能。该手册将Python的所有关键语法和概念进行了精炼的总结&#xff0c;并以易于理解和记忆的方式呈现。以下是手册的主要特点和内容概述&a…...

【Pytorch实用教程】如何在多个GPU上使用分布式数据并行进行训练模型

文章目录 1. 代码(可直接运行,含随机生成的训练数据)2. 代码的详细解释2.1. 导入必要的库和模块2.2. 设置每个进程的初始设置2.3. 随机生成数据集类 `RandomDataset`2.4. 训练函数 `train`1. 代码(可直接运行,含随机生成的训练数据) 以下是一个基于PyTorch的多GPU分布式…...

PIL,OpenCV,Pytorch处理图像时的通道顺序(颜色,长宽深)

项目颜色通道顺序长宽通道顺序数据类型取值范围PILRGBHWCndarray0-255 (byte)OpenCVBGRHWCndarray0-255 (byte)PyTorchRGB/BGR (取决于如何读取)(N)CHWtensor0-1 (float, 标准化后); 0-255 (int, 未标准化) 注意以下几点&#xff1a; 颜色通道顺序&#xff1a;PIL默认使用RGB顺…...

经纬恒润亮相2024世界智能产业博览会

近日&#xff0c;以“智行天下 能动未来”为主题的2024世界智能产业博览会&#xff08;以下简称“智博会”&#xff09;在国家会展中心&#xff08;天津&#xff09;成功举办。本次智博会上&#xff0c;经纬恒润自主研发的汽车电子产品联合天津&#xff08;西青&#xff09;国家…...

Python序列化和反序列化

一.序列化和反序列化 在Python中&#xff0c;序列化&#xff08;Serialization&#xff09;和反序列化&#xff08;Deserialization&#xff09;是处理对象数据的过程&#xff0c;主要用于对象的存储或网络传输。 序列化&#xff08;Serialization&#xff09; 序列化是将Pyth…...

Stream toArray 好过collect

toArray 比collect 更好用&#xff0c;这样就不需要判断Null。 if(_user.getUserRole()!null) {_user.setRole(_roleList.stream().filter(_e->_e.getRoleId()_user.getUserRole()).toArray(Role[]::new)[0]); } if(_user.getUserRole()!null) {_user.setRole(_roleList.s…...

qt/c++/mysql教务管理系统

简介 qt/c/mysql教务管理系统 学生端&#xff0c;教师端&#xff0c;管理员端 演示 qt/c/mysql教务管理系统 源码获取 printf("白嫖勿扰,需要的加v%s","ywj17347418171");...

Echarts公共方法

Vue引入Echarts install 1.安装Echartsnpm install echarts --save 2.项目全局引入形式--#main.js 全局引入形式import * as echarts from "echarts"Vue.prototype.$echarts echarts 公共方法JS /*** author: wangjie* description: 通用echarts图表封装* date: …...

鸿蒙学习(二)

文章目录 1、弹窗2、走马灯&#xff08;实现轮播图效果&#xff09;3、注解6、多选框、单选框7、Stack8、TextTimer9、DatePicker 1、弹窗 显示提示信息或者用于用户交互 导入模块 prompt 接口 showToast:显示toast showDialog:显示对话框 showContextMenu:显示上下文菜单 sh…...

企业机构营销目前106短信群发还有用吗?此文告诉你该如何抉择!

在当今竞争激烈的企业营销环境中&#xff0c;106短信群发平台依然是众多企业机构青睐的营销工具之一。尽管互联网技术的发展带来了多样化的沟通方式&#xff0c;但106短信群发凭借其直达性强、成本低廉、覆盖广泛等优势&#xff0c;仍然保持着不错的营销效果。然而&#xff0c;…...

DJYGUI AI低代码图形编程开发平台:开启嵌入式软件图形编程新纪元

在科技高速发展的当今时代&#xff0c;软件开发行业对创新和高效的需求日益增长。DJYGUI AI低代码图形编程开发平台的出现&#xff0c;为智能屏、物联屏、串口屏等嵌入式显示设备领域带来了全新的机遇。该平台由都江堰操作系统 AI 代码自动生成平台研发&#xff0c;具有显著的优…...

为什么不能在foreach中删除元素

文章目录 快速失败机制&#xff08;fail-fast&#xff09;for-each删除元素为什么报错原因分析逻辑分析 如何正确的删除元素remove 后 breakfor 循环使用 Iterator 总结 快速失败机制&#xff08;fail-fast&#xff09; In systems design, a fail-fast system is one which i…...

python学习-tuple及str

为什么需要元组 定义元组 元组的相关操作 元组的相关操作 - 注意事项 元组的特点 字符串 字符串的下标&#xff08;索引&#xff09; 同元组一样&#xff0c;字符串是一个&#xff1a;无法修改的数据容器。 如果必须要修改字符串&#xff0c;只能得到一个新的字符串&#xff…...

Python深度理解系列之【排序算法——冒泡排序】

读者大大们好呀&#xff01;&#xff01;!☀️☀️☀️ &#x1f440;期待大大的关注哦❗️❗️❗️ &#x1f680;欢迎收看我的主页文章➡️木道寻的主页 文章目录 &#x1f525;前言&#x1f680;冒泡排序python实现算法实现图形化算法展示 ⭐️⭐️⭐️总结 &#x1f525;前…...

边界框在目标检测中的作用与应用

目标检测是计算机视觉领域的核心任务之一&#xff0c;旨在从图像或视频中识别和定位感兴趣的目标。边界框&#xff08;Bounding Box&#xff09;是目标检测中常用的一种表示方法&#xff0c;用于确定目标在图像中的确切位置。本文将详细探讨边界框的概念、它在目标检测中的角色…...

linux 环境报错:Peer reports incompatible or unsupported protocol version

出现问题的原因&#xff1a; curl 不兼容或不支持的协议版本。 解决方案&#xff1a; yum update -y nss curl libcurl如此继续之前的操作即可。...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module

1、为什么要修改 CONNECT 报文&#xff1f; 多租户隔离&#xff1a;自动为接入设备追加租户前缀&#xff0c;后端按 ClientID 拆分队列。零代码鉴权&#xff1a;将入站用户名替换为 OAuth Access-Token&#xff0c;后端 Broker 统一校验。灰度发布&#xff1a;根据 IP/地理位写…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...