指针(C语言)从0到1掌握指针,为后续学习c++打下基础

目录

一,指针

二,内存地址和指针

 1,什么是内存地址

2,指针在不同系统下所占内存

三,指针的声明和初始化以及类型

1,指针的声明

 2,指针 的初始化

1, 初始化方式优点及适用场景

4,指针的声明初始化类型

四,野指针(永远都要避免) 

1,野指针的定义

2,野指针产生的原因

1,指针没有初始化

2,释放内存后未置空 

3.局部变量超出作用域 

3,野指针的危害 

4,如何避免野指针

 五,取地址符和解引用

1,取地址符&

2,解引用 *

六,指针的算术运算

1. 指针加法

2. 指针减法 

 3. 指针自增/自减

 4. 指针与整数的比较

七,指针与数组

1,定义

2,初始化

3,指针数组与字符串

八,指针与函数

1. 函数参数传递指针

2. 函数返回指针 

3. 函数指针 

4,注意事项(必看)

九,多级指针

1. 多级指针的定义与初始化

1,定义

2,初始化

2. 多级指针的使用场景

1,动态二维数组

2,函数参数传递

3. 多级指针的注意事项


一,指针

在C语言中,指针是一种特殊的数据类型,用于存储另一个变量的内存地址。这使得程序可以直接操作计算机的物理内存位置,从而实现高效的内存管理和灵活的数据结构设计。


二,内存地址和指针

1,每个变量存储在内存中的唯一位置。

2,指针是存储内存地址的特殊变量。

int var = 10;
int *ptr = &var;  // ptr存储var的地址

 1,什么是内存地址

内存是计算机用于存储数据和程序的地方,它被划分成一个个连续的存储单元,每个存储单元都有一个唯一的编号,这个编号就是内存地址。内存地址就像图书馆里书架上的格子编号一样,通过它可以准确地找到和操作存储在相应位置的数据。CPU 通过内存地址来访问和读写内存中的数据,数据在内存中的存储、读取和修改等操作都依赖于内存地址来确定具体位置。

2,指针在不同系统下所占内存

指针占用的内存大小取决于所使用的计算机系统的架构和编译器等因素:

以下是一个简易输出在64位32位的情况下所占用字节。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() 
{int* intPtr;                   size_t ptrSize = sizeof(intPtr);printf("int指针占用的字节数: %zu 字节\n", ptrSize);return 0;
}

在 32 位系统中,指针通常占用 4 个字节的内存空间。这是因为 32 位系统的地址总线是 32 位的,它能够表示的地址范围是2的32次方个不同的地址,所以需要 4 个字节来存储一个地址。

在 64 位系统中,指针一般占用 8 个字节的内存。因为 64 位系统的地址总线是 64 位,可表示的地址范围是2的64次方个,所以需要 8 个字节来存储一个地址。


三,指针的声明和初始化以及类型

1,指针的声明

指针是一种变量,它存储的是内存地址。通过指针,我们可以直接访问和操作内存中的数据。定义指针的一般形式为。

数据类型 *指针变量名;

 1.这里定义了一个名为p的指针变量,它可以指向一个int类型的数据。 

int *p;

 2,指针 的初始化

1, 指针在定义后可以进行初始化,使其指向一个已存在的变量。

int num = 10;
int *p = &num;

2,里&是取地址运算符,它获取变量num的内存地址,并将其赋值给指针p,此时p就指向了变量num。也可以先定义指针,再进行赋 

int num = 10;
int *p;
p = &num;

3,这是最安全的初始化方式之一,将指针初始化位null(空指针),表示指针不知想任何有效的内存地址。null是一个特殊的指针值,通常定义位0。

  int* p = NULL;  // 初始化为NULLif(p == NULL) {printf("p是NULL\n");}

4,通过动态内存分配函数(如malloc、callocrealloc)分配内存,并将指针初始化为分配的内存地址。这种方式适用于需要在运行时动态分配内存的场景(仅展示malloc)。 

#include <stdio.h>
#include <stdlib.h>
int main() 
{int* p = (int*)malloc(sizeof(int));  // 动态分配一个整型变量的内存if (p != NULL) {*p = 10;  // 使用分配的内存printf("%d\n", *p);free(p);  // 释放分配的内存}else {printf("失败\n");}return 0;
}

1, 初始化方式优点及适用场景

初始化方式优点适用场景
初始化为NULL避免野指针错误不确定指针指向
初始化为动态分配的内存动态管理内存需要动态分配内存
初始化为变量的地址简单直观,方便操作变量需要通过指针修改变量

4,指针的声明初始化类型

在C语言中,指针的初始化不单单只有int类型可以初始化,还有以下:

int *p1;         // 整型指针
char *p2;        // 字符指针
float *p3;       // 浮点指针
double *p4;      // 双精度指针
void *p5;        // 无类型指针

四,野指针(永远都要避免) 

野指针是C语言中一个非常危险且常见的问题,它是指向一个无效、未分配或已经被释放的内存地址的指针。野指针的存在可能导致程序出现不可预知的行为,甚至崩溃。以下是关于野指针的详细解释,包括定义、产生原因、危害以及预防方法

1,野指针的定义

野指针是指向未知或无效内存区域的指针。它不是NULL指针,而是指向已经被释放或从未被分配的内存的指针。野指针的值是随机的,因此它可能指向任何内存位置,这使得野指针的使用非常危险。

2,野指针产生的原因

1,指针没有初始化

任何指针变量刚被创建时不会自动成为 NULL 指针,其缺省值是随机的。如在 C 语言中 int *p; 这样声明一个指针后,如果不对其初始化就使用,它就是野指针。

int *p;  // 未初始化,p是一个野指针
*p = 10;  // 随机地址赋值,可能导致程序崩溃

2,释放内存后未置空 

当使用 free 或 delete 等操作释放了动态分配的内存后,如果没有将指针设置为 NULL,而是继续使用该指针,那么它就会变成野指针。例如在 C 语言中,int *p = (int *)malloc(sizeof(int)); free(p); 执行完 free 后,p 就成为野指针。

int *p = (int*)malloc(sizeof(int)); // 分配内存
free(p);  // 释放内存,但 p 仍指向原地址
// 此时 p 成为野指针,访问 *p 会导致未定义行为

3.局部变量超出作用域 

不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。例如在函数内部定义一个局部变量,然后返回指向该局部变量的指针,当函数结束后,该局部变量的内存被释放,指针就成了野指针

int* createDanglingPointer() 
{int localVar = 10;return &localVar; // 返回局部变量的地址
}// 函数结束后,localVar 内存被释放,返回的指针变为野指针

3,野指针的危害 

问题表现
程序崩溃访问已释放的内存可能导致段错误
数据损坏野指针可能意外修改其他有效内存区域的数据。
安全问题攻击者可能利用野指针篡改程序逻辑
调试困难野指针引发的错误具有随机性,难以复现和定位。

4,如何避免野指针

 1,初始化指针:在声明指针时,如果可能的话,立即将其初始化为 NULL 或一个有效的内存地址。

2,释放内存后设置指针为 NULL:在释放了指针所指向的内存后,立即将指针设置为 NULL,以防止野指针的产生。

3,避免数组越界:确保数组访问在有效的索引范围内。使用循环和条件语句来检查索引是否在有效范围内。

4,避免返回局部变量地址:确保返回的指针指向堆内存或静态存储区的数据。

5,使用工具进行内存检查:使用如 Valgrind 这样的内存检查工具可以帮助发现野指针和其他内存相关的问题。(Valgrind、Clang Static Analyzer)


 五,取地址符和解引用

1,取地址符&

去支付是指针的核心要在,没有去支付就算不的它是一个指针。

int age = 25;
int *ptr = &age;

2,解引用 *

指针是一个变量,它存储的是另一个变量的内存地址。解引用操作就是通过指针访问其所指向的内存地址中的值。在 C 语言中,使用星号 * 来进行解引用操作

printf("%d", *ptr);  // 输出25
*ptr = 30;           // 修改实际变量值

六,指针的算术运算

 指针的算术运算是C语言中一个非常重要的概念,它允许我们通过指针来访问和操作数组、字符串等数据结构。指针的算术运算包括加法、减法和自增/自减运算。

1. 指针加法

指针加法是指将一个整数加到指针上,结果是一个新的指针,它指向原指针所指向的地址加上该整数乘以指针类型所占字节数的内存位置。

#include <stdio.h>
int main() 
{int arr[5] = { 10, 20, 30, 40, 50 };int* p = arr;  // 指针p指向数组arr的首元素// 指针p加上2p = p + 2;printf("指针移动后所指向的值: %d\n", *p);  // 输出30return 0;
}

2. 指针减法 

指针减法是指将一个整数从指针中减去,结果是一个新的指针,它指向原指针所指向的地址减去该整数乘以指针类型所占字节数的内存位置。

#include <stdio.h>
int main() 
{int arr[5] = { 10, 20, 30, 40, 50 };int* p = arr + 4;  // 指针p指向数组arr的最后一个元素// 指针ptr减去1p = p - 1;printf("指针移动后所指向的值: %d\n", *p);  // 输出40return 0;
}

 3. 指针自增/自减

指针自增(p++)和自减(p--)运算符用于将指针移动到下一个或上一个元素的位置。这相当于在指针上加或减1。

#include <stdio.h>
int main() 
{char str[] = "Hello";char* c = str;while (*c != '\0') {putchar(*c);c++;        // 逐个访问字符}
}

 4. 指针与整数的比较

指针可以与整数进行比较,但这种比较通常没有意义,因为指针的值是内存地址,而整数是数值。唯一有意义的比较是指针与NULL的比较,这可以用来检查指针是否为空。

#include <stdio.h>
int main() {int* p = NULL;if (p == NULL) {printf("NULL\n");}return 0;
}

七,指针与数组

在 C 语言中,指针数组是一种非常实用的数据结构,它结合了指针和数组的特性。下面将从定义、初始化、使用场景、注意事项等方面详细介绍指针数组。

1,定义

指针数组是一个数组,数组中的每个元素都是一个指针。

数据类型 *数组名[数组大小];

2,初始化

指针数组可以在定义时进行初始化,也可以在后续的代码中逐个赋值。

#include <stdio.h>
int main() 
{int num1 = 10, num2 = 20, num3 = 30;int* ptrArray[3] = { &num1, &num2, &num3 };for (int i = 0; i < 3; i++) {printf("ptrArray[%d] 指向的值: %d\n", i, *ptrArray[i]);}return 0;
}

3,指针数组与字符串

指针数组在处理字符串时非常有用,因为 C 语言中的字符串实际上是字符数组,我们可以使用指针数组来存储多个字符串。

#include <stdio.h>
int main() 
{char* strArray[] = { "Hello", "World", "C Language" };for (int i = 0; i < 3; i++) {printf("strArray[%d]: %s\n", i, strArray[i]);}return 0;
}

如上述示例所示,指针数组可以方便地存储和操作多个字符串,比二维字符数组更加灵活。

八,指针与函数

在 C 语言中,指针和函数有着紧密的联系,它们相互配合可以实现许多强大的功能。下面从函数参数传递指针、函数返回指针、函数指针这三个方面详细介绍指针与函数的关系。

1. 函数参数传递指针

在 C 语言里,函数参数传递分为值传递和地址传递(指针传递)。值传递只是将实参的值复制给形参,在函数内部对形参的修改不会影响到实参;而地址传递是将实参的地址传递给形参,这样函数内部就可以通过指针直接操作实参所指向的内存空间,从而修改实参的值。

#include <stdio.h>
// 交换两个整数的值,使用指针作为参数
void swap(int* a, int* b)
{int temp = *a;*a = *b;*b = temp;
}
int main() 
{int x = 10, y = 20;printf("交换前: x = %d, y = %d\n", x, y);swap(&x, &y);printf("交换后: x = %d, y = %d\n", x, y);return 0;
}

2. 函数返回指针 

函数可以返回一个指针,这样可以将函数内部动态分配的内存地址或者某个变量的地址返回给调用者。需要注意的是,返回的指针必须指向有效的内存区域,避免返回局部变量的地址,因为局部变量在函数执行结束后会被销毁,其地址将变得无效。

#include <stdio.h>
#include <stdlib.h>
// 动态分配内存并存储一个整数,返回指向该内存的指针
int* createInt(int value) 
{int* ptr = (int*)malloc(sizeof(int));if (ptr != NULL) {*ptr = value;}return ptr;
}
int main() 
{int* numPtr = createInt(100);if (numPtr != NULL) {printf("动态分配内存中存储的值: %d\n", *numPtr);free(numPtr);  // 释放动态分配的内存}return 0;
}

3. 函数指针 

函数指针是指向函数的指针变量,它可以存储函数的入口地址,通过函数指针可以调用相应的函数。函数指针的定义形式为:返回类型(*指针名)(参数列表);

#include <stdio.h>
// 定义两个函数
int add(int a, int b) 
{return a + b;
}
int subtract(int a, int b) 
{return a - b;
}
int main() 
{// 定义一个函数指针,指向返回值为int,参数为两个int类型的函数int (*funcPtr)(int, int);// 让函数指针指向add函数funcPtr = add;printf("add函数调用结果: %d\n", funcPtr(5, 3));// 让函数指针指向subtract函数funcPtr = subtract;printf("subtract函数调用结果: %d\n", funcPtr(5, 3));return 0;
}

4,注意事项(必看)

  1. 内存管理:当函数返回指针时,要确保返回的指针指向有效的内存区域,并且在不再使用时及时释放动态分配的内存,防止内存泄漏。
  2. 空指针检查:在使用函数返回的指针或函数指针之前,最好进行空指针检查,避免对空指针进行操作导致程序崩溃。
  3. 函数指针类型匹配:函数指针的类型必须与所指向的函数的返回类型和参数列表完全匹配,否则会导致编译错误或未定义行为。

九,多级指针

多级指针,也就是指针的指针,在 C 语言里是一个较为高级且强大的特性。下面会从多级指针的定义、初始化、使用场景、注意事项等方面进行详细介绍。

1. 多级指针的定义与初始化

1,定义

多级指针是指指向指针的指针,常见的有二级指针、三级指针等。

数据类型 *指针变量名;    //一级指针
数据类型 **指针变量名;   //二级指针
数据类型 ***指针变量名;  //三级指针

2,初始化

多级指针的初始化需要关联到一个已存在的指针。

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

2. 多级指针的使用场景

1,动态二维数组

在 C 语言里,可以借助二级指针来动态创建二维数组。

#include <stdio.h>
#include <stdlib.h>
int main() 
{int rows = 3, cols = 4;int** matrix;// 为行指针分配内存matrix = (int**)malloc(rows * sizeof(int*));if (matrix == NULL) {fprintf(stderr, "内存分配失败\n");return 1;}// 为每一行分配内存for (int i = 0; i < rows; i++) {matrix[i] = (int*)malloc(cols * sizeof(int));if (matrix[i] == NULL) {fprintf(stderr, "内存分配失败\n");return 1;}}// 初始化二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {matrix[i][j] = i * cols + j;}}// 输出二维数组for (int i = 0; i < rows; i++) {for (int j = 0; j < cols; j++) {printf("%d ", matrix[i][j]);}printf("\n");}// 释放内存for (int i = 0; i < rows; i++) {free(matrix[i]);}free(matrix);return 0;
}

2,函数参数传递

在函数中使用多级指针作为参数,可以修改调用函数中的指针变量。

#include <stdio.h>
#include <stdlib.h>
void allocateMemory(int** ptr) 
{*ptr = (int*)malloc(sizeof(int));if (*ptr != NULL) {**ptr = 100;}
}
int main() 
{int* p = NULL;allocateMemory(&p);if (p != NULL) {printf("分配内存中存储的值: %d\n", *p);free(p);}return 0;
}

3. 多级指针的注意事项

  1. 内存管理:当使用多级指针进行动态内存分配时,必须注意内存的分配和释放顺序。一般来说,要先释放内层指针指向的内存,再释放外层指针指向的内存,避免内存泄漏。例如在上面动态二维数组的例子中,要先释放每一行的内存,再释放存储行指针的内存。

  2. 查空指针检:在使用多级指针之前,要进行空指针检查,防止对空指针进行解引用操作,从而避免程序崩溃。比如在分配内存时,如果返回 NULL,就需要进行错误处理。

  3. 理解解引用操作:多级指针涉及多次解引用操作,要清楚每次解引用所访问的对象。例如,二级指针 **pp 需要两次解引用才能访问到最终的数据,理解这个过程有助于正确使用多级指针。

 

 

 

 

 

 

 

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

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

相关文章

【已解决】windows7虚拟机安装VMtools频繁报错

为了在虚拟机VMware中安装win7&#xff0c;题主先在网上下载了windows7 professional版本的镜像&#xff0c;在vmware中安装vmtools时报错&#xff0c;信息如下 &#xff08;安装程序无法继续&#xff0c;本程序需要您将此虚拟机上安装的操作系统更新到SP1&#xff09; 然后就…

单词翻转(信息学奥赛一本通1144)

题目来源 信息学奥赛一本通&#xff08;C版&#xff09;在线评测系统 题目描述 1144&#xff1a;单词翻转 时间限制: 1000 ms 内存限制: 65536 KB 提交数:60098 通过数: 26099 【题目描述】 输入一个句子(一行)&#xff0c;将句子中的每一个单词翻转后输出。 【输入…

从0到1:C++ 开启游戏开发奇幻之旅(二)

目录 游戏开发核心组件设计 游戏循环 游戏对象管理 碰撞检测 人工智能&#xff08;AI&#xff09; 与物理引擎 人工智能 物理引擎 性能优化技巧 内存管理优化 多线程处理 实战案例&#xff1a;开发一个简单的 2D 射击游戏 项目结构设计 代码实现 总结与展望 游戏…

【Block总结】DynamicFilter,动态滤波器降低计算复杂度,替换传统的MHSA|即插即用

论文信息 标题: FFT-based Dynamic Token Mixer for Vision 论文链接: https://arxiv.org/pdf/2303.03932 关键词: 深度学习、计算机视觉、对象检测、分割 GitHub链接: https://github.com/okojoalg/dfformer 创新点 本论文提出了一种新的标记混合器&#xff08;token mix…

(done) MIT6.S081 2023 学习笔记 (Day6: LAB5 COW Fork)

网页&#xff1a;https://pdos.csail.mit.edu/6.S081/2023/labs/cow.html 任务1&#xff1a;Implement copy-on-write fork(hard) (完成) 现实中的问题如下&#xff1a; xv6中的fork()系统调用会将父进程的用户空间内存全部复制到子进程中。如果父进程很大&#xff0c;复制过程…

鸢尾花书01---基本介绍和Jupyterlab的上手

文章目录 1.致谢和推荐2.py和.ipynb区别3.Jupyterlab的上手3.1入口3.2页面展示3.3相关键介绍3.4代码的运行3.5重命名3.6latex和markdown说明 1.致谢和推荐 这个系列是关于一套书籍&#xff0c;结合了python和数学&#xff0c;机器学习等等相关的理论&#xff0c;总结的7本书籍…

【愚公系列】《循序渐进Vue.js 3.x前端开发实践》033-响应式编程的原理及在Vue中的应用

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…

【javaweb项目idea版】蛋糕商城(可复用成其他商城项目)

该项目虽然是蛋糕商城项目&#xff0c;但是可以复用成其他商城项目或者购物车项目 想要源码的uu可点赞后私聊 技术栈 主要为&#xff1a;javawebservletmvcc3p0idea运行 功能模块 主要分为用户模块和后台管理员模块 具有商城购物的完整功能 基础模块 登录注册个人信息编辑…

为什么LabVIEW适合软硬件结合的项目?

LabVIEW是一种基于图形化编程的开发平台&#xff0c;广泛应用于软硬件结合的项目中。其强大的硬件接口支持、实时数据采集能力、并行处理能力和直观的用户界面&#xff0c;使得它成为工业控制、仪器仪表、自动化测试等领域中软硬件系统集成的理想选择。LabVIEW的设计哲学强调模…

Fort Firewall:全方位守护网络安全

Fort Firewall是一款专为 Windows 操作系统设计的开源防火墙工具&#xff0c;旨在为用户提供全面的网络安全保护。它基于 Windows 过滤平台&#xff08;WFP&#xff09;&#xff0c;能够与系统无缝集成&#xff0c;确保高效的网络流量管理和安全防护。该软件支持实时监控网络流…

【PyTorch】6.张量形状操作:在深度学习的 “魔方” 里,玩转张量形状

目录 1. reshape 函数的用法 2. transpose 和 permute 函数的使用 4. squeeze 和 unsqueeze 函数的用法 5. 小节 个人主页&#xff1a;Icomi 专栏地址&#xff1a;PyTorch入门 在深度学习蓬勃发展的当下&#xff0c;PyTorch 是不可或缺的工具。它作为强大的深度学习框架&am…

[STM32 - 野火] - - - 固件库学习笔记 - - -十三.高级定时器

一、高级定时器简介 高级定时器的简介在前面一章已经介绍过&#xff0c;可以点击下面链接了解&#xff0c;在这里进行一些补充。 [STM32 - 野火] - - - 固件库学习笔记 - - -十二.基本定时器 1.1 功能简介 1、高级定时器可以向上/向下/两边计数&#xff0c;还独有一个重复计…

Cyber Security 101-Build Your Cyber Security Career-Security Principles(安全原则)

了解安全三元组以及常见的安全模型和原则。 任务1&#xff1a;介绍 安全已成为一个流行词;每家公司都想声称其产品或服务是安全的。但事实真的如此吗&#xff1f; 在我们开始讨论不同的安全原则之前&#xff0c;了解我们正在保护资产的对手至关重要。您是否试图阻止蹒跚学步…

python:斐索实验(Fizeau experiment)

斐索实验&#xff08;Fizeau experiment&#xff09;是在1851年由法国物理学家阿曼德斐索&#xff08;Armand Fizeau&#xff09;进行的一项重要实验&#xff0c;旨在测量光在移动介质中的传播速度。这项实验的结果对当时的物理理论产生了深远的影响&#xff0c;并且在后来的相…

青少年CTF练习平台 贪吃蛇

题目 CtrlU快捷键查看页面源代码 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>贪吃蛇游戏</title><style>#gameCanvas {border: 1px solid black;}</style> </head>…

芯片AI深度实战:基础篇之Ollama

有这么多大模型&#xff0c;怎么本地用&#xff1f; Ollama可以解决这一问题。不依赖GPU&#xff0c;也不需要编程。就可以在CPU上运行自己的大模型。 软件甚至不用安装&#xff0c;直接在ollama官网下载可执行文件即可。 现在最流行的deepseek-r1也可以使用。当然还有我认为最…

本地部署deepseek模型步骤

文章目录 0.deepseek简介1.安装ollama软件2.配置合适的deepseek模型3.安装chatbox可视化 0.deepseek简介 DeepSeek 是一家专注于人工智能技术研发的公司&#xff0c;致力于打造高性能、低成本的 AI 模型&#xff0c;其目标是让 AI 技术更加普惠&#xff0c;让更多人能够用上强…

DeepSeek R1中提到“知识蒸馏”到底是什么

在 DeepSeek-R1 中&#xff0c;知识蒸馏&#xff08;Knowledge Distillation&#xff09;是实现模型高效压缩与性能优化的核心技术之一。在DeepSeek的论文中&#xff0c;使用 DeepSeek-R1&#xff08;教师模型&#xff09;生成 800K 高质量训练样本&#xff0c;涵盖数学、编程、…

关联传播和 Python 和 Scikit-learn 实现

文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数&#xff1a;集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…

通过配置代理解决跨域问题(Vue+SpringBoot项目为例)

跨域问题&#xff1a; 是由浏览器的同源策略引起的&#xff0c;同源策略是一种安全策略&#xff0c;用于防止一个网站访问其他网站的数据。 同源是指协议、域名和端口号都相同。 跨域问题常常出现在前端项目中&#xff0c;当浏览器中的前端代码尝试从不同的域名、端口或协议…