基础知识-指针
1、指针的基本概念
1.1 什么是指针
1.1.1 指针的定义
指针是一种特殊的变量,与普通变量存储具体数据不同,它存储的是内存地址。在计算机程序运行时,数据都被存放在内存中,而指针就像是指向这些数据存放位置的 “路标”。通过指针,程序可以间接访问和操作对应内存地址的数据。
1.1.2 指针与普通变量的区别
普通变量直接存储数据值,比如 int num = 10; ,变量 num 中直接存放的是数值 10 。而指针变量存储的是内存地址,例如 int num = 10; int *ptr = # ,指针 ptr 存储的是变量 num 在内存中的地址,要获取 num 的值,需要通过解引用操作 *ptr 。
此外,普通变量的运算基于其存储的数据类型,如 int 型变量可进行加减乘除;指针变量的运算则围绕内存地址偏移,比如 ptr++ 会根据 int 类型数据在内存中占用的字节数(通常 4 字节),将指针指向下一个 int 数据的地址。
1.2 内存与地址的关系
内存是计算机用于临时存储数据和程序的硬件设备,就像一个庞大的仓库,被划分成一个个连续的小格子,每个小格子都有唯一的编号,CPU 通过这些编号,找到相应的内存空间,这个编号就是内存地址。数据在存储时,会被分配到特定的内存地址空间中。地址就如同仓库格子的编号,程序通过地址来准确找到数据在内存中的存放位置,从而实现对数据的读写操作 。当定义一个变量时,系统会在内存中为其分配一定的空间,并赋予对应的内存地址,而指针变量存储的就是这些地址,以此建立起对数据的间接访问通道。
形象地来说,内存是一栋楼,一个内存单元是一户人家,指针是门牌号,CPU是我们,我们通过门牌号可以找到那户人家住的地方。
1.2.1 计算机内存结构简介
计算机内存通常采用线性编址结构,从低地址到高地址连续排列。在逻辑上,内存可分为多个区域,如栈区、堆区、全局数据区、代码区等。
- 栈区:主要用于存储函数调用时的局部变量、函数参数等,遵循后进先出原则
- 堆区:用于动态内存分配,可通过 malloc (C 语言)或 new (C++ 语言)等函数在堆上申请内存
- 全局数据区:存放全局变量和静态变量
- 代码区:存储程序的可执行代码
指针在不同内存区域的数据操作中都发挥着关键作用,比如在堆区通过指针管理动态分配的内存,在栈区利用指针传递函数参数等。
1.2.2 地址的作用与表示
地址的核心作用是标识内存中数据的存储位置,它使得程序能够准确找到并操作数据。
在计算机中,地址通常以二进制形式存储和处理,但在编程中,常以十六进制数表示,便于阅读和理解。在 C 语言的调试过程中,打印指针变量的值,显示的就是十六进制的内存地址。
2、指针的基本语法
2.1 指针的声明与初始化
2.1.1 指针的声明
语法格式:数据类型 *指针名;
注:“数据类型” 表明该指针所指向变量的类型,“指针变量名” 则是用户为指针取的名字
int *ptr; //声明一个指向int类型数据的指针ptr
float *fptr; //声明一个指向float类型数据的指针fptr
2.1.2 指针的初始化
指针初始化就是在声明指针的同时为其赋予一个合法的内存地址。
常见的初始化方式有:
- 初始化为 NULL
- 初始化为变量的地址
- 初始化为动态分配的内存地址
//初始化为 NULL
int *ptr = NULL;//初始化为变量的地址
int num = 10;
int *ptr = #//初始化为动态分配的内存地址
int *ptr = (int *)malloc(sizeof(int));
2.2 取地址操作符&
作用:用于获取变量的内存地址。
#include <stdio.h>int main()
{int num = 10;int *ptr = # //使用取地址操作符&获取变量num的地址并赋给指针ptrprintf("变量 num 的地址: %p\n", (void *)&num);printf("指针 ptr 存储的地址: %p\n", (void *)ptr);return 0;
}
在使用 printf 函数输出指针的值时,%p 格式说明符要求对应的参数是 void * 类型。这是由于 %p 用于以十六进制形式输出指针所存储的内存地址,而 void * 类型的指针可以存储任意类型的地址,能确保输出的是纯粹的地址信息。
2.3 解引用操作符*
作用1:通过指针访问所指向的值。
#include <stdio.h>int main()
{int num = 10;int *ptr = #int value = *ptr; //通过解引用操作符*获取指针ptr所指向的值printf("指针 ptr 所指向的值: %d\n", value); //输出为10return 0;
}
作用2:修改指针指向的值。
#include <stdio.h>int main()
{int num = 10;int *ptr = #*ptr = 20; //通过解引用操作符*修改指针ptr所指向的值printf("变量 num 的新值: %d\n", num); //输出为20return 0;
}
2.4 空指针
空指针表示不指向任何有效内存地址的指针。
- 在 C 语言中,通常用 NULL 来表示空指针
- 在 C++ 11 及以后的版本中,推荐使用 nullptr
int main()
{//C环境下int *ptr = NULL; //C语言中使用NULL初始化空指针printf("指针 ptr 的值: %p\n", (void *)ptr);//C++环境下int *ptr = nullptr; //C++中使用nullptr初始化空指针std::cout << "指针 ptr 的值: " << ptr << std::endl;return 0;
}
3、指针的核心应用
3.1 函数参数传递
3.1.1 值传递
在值传递中,函数调用时会将实参的值复制一份给形参。函数内部对形参的任何修改都只会影响形参本身,而不会影响到实参。
#include <stdio.h>void changeValue(int num)
{num = 20;printf("函数内部 num 的值: %d\n", num); //输出为20
}int main()
{int num = 10;changeValue(num);printf("函数外部 num 的值: %d\n", num); //输出依旧为10,值传递不影响实参return 0;
}
3.1.2 指针传递
指针传递是将实参的地址传递给形参,形参是一个指针,它指向实参所在的内存地址。因此,函数内部可以通过指针来修改实参的值。
#include <stdio.h>void changeValue(int *ptr)
{*ptr = 20;printf("函数内部指针指向的值: %d\n", *ptr); //输出为20
}int main()
{int num = 10;changeValue(&num);printf("函数外部 num 的值: %d\n", num); //输出为20,指针传递会改变实参return 0;
}
3.2 动态内存分配
- C 语言:malloc、calloc、realloc 和 free
- C++ 语言:new 和 delete
3.2.1 C 语言
malloc
用于在堆上分配指定大小的内存块,返回一个指向该内存块起始地址的指针。如果分配失败,返回 NULL。
#include <stdio.h>
#include <stdlib.h>int main()
{int *ptr = (int *)malloc(5 * sizeof(int));if (ptr == NULL){printf("内存分配失败\n");return 1;}//初始化数组元素for (int i = 0; i < 5; i++) {ptr[i] = i;}//输出数组元素for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");//释放内存free(ptr);ptr = NULL;return 0;
}
calloc
用于在堆上分配指定数量和大小的内存块,并将其初始化为 0。返回一个指向该内存块起始地址的指针。如果分配失败,返回 NULL。
#include <stdio.h>
#include <stdlib.h>int main()
{int *ptr = (int *)calloc(5, sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}//输出数组元素,由于calloc会初始化为0,所以输出全为0for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");//释放内存free(ptr);ptr = NULL;return 0;
}
realloc
用于调整已分配内存块的大小。可以扩大或缩小内存块。返回一个指向新内存块起始地址的指针。如果分配失败,返回 NULL,原内存块不会被释放。
#include <stdio.h>
#include <stdlib.h>int main()
{int *ptr = (int *)malloc(3 * sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");return 1;}//初始化数组元素for (int i = 0; i < 3; i++) {ptr[i] = i;}//扩大内存块int *newPtr = (int *)realloc(ptr, 5 * sizeof(int));if (newPtr == NULL) {printf("内存重新分配失败\n");free(ptr);ptr = NULL;return 1;}ptr = newPtr;//初始化新增的数组元素for (int i = 3; i < 5; i++) {ptr[i] = i;}//输出数组元素for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");//释放内存free(ptr);ptr = NULL;return 0;
}
分析代码里的内存分配情况:
- 借助 malloc 函数分配了 3 块 int 类型的内存,并且把指向这块内存的指针赋值给 ptr
- 利用 realloc 函数把之前分配的 3 块 int 类型内存重新分配为 5 块 int 类型的内存。要是重新分配成功,realloc 函数会返回一个指向新内存块的指针,然后把这个指针赋值给 newPtr
- 把 newPtr 的值赋给 ptr,这样 ptr 就指向了新分配的 5 块 int 类型的内存
注意:先分配的 3 块内存并没有单独释放,而是在重新分配内存后,将其包含在新的内存块中,最终一起释放。
free
用于释放之前通过 malloc、calloc 或 realloc 分配的内存块。释放后的内存可以被再次分配。
注意:释放后的指针成为野指针,建议将其置为 NULL,避免误操作。
3.2.2 C++ 语言
new
用于在堆上分配内存并构造对象。对于基本数据类型,直接分配内存;对于类类型,会调用构造函数。
#include <iostream>
using namespace std;int main()
{//分配一个int型内存,并初始化为10,也可以不初始化,直接new int就可以int *ptr = new int(10);cout << *ptr << endl;//分配一个int型数组,长度为5int *arr = new int[5];for (int i = 0; i < 5; i++) {arr[i] = i;}for (int i = 0; i < 5; i++) {cout << arr[i] << " ";}cout << endl;// 释放内存delete ptr;delete[] arr; //释放数组return 0;
}
delete
用于释放通过 new 分配的内存。对于基本数据类型,直接释放内存;对于类类型,会调用析构函数。
注意:释放数组时需要使用 delete[ ],否则会导致内存泄漏。
3.2.3 结构体与指针的结合使用
结构体可以将不同类型的数据组合在一起,而指针可以方便地访问和操作结构体。可以定义指向结构体的指针,通过指针来访问结构体的成员。
#include <stdio.h>
#include <stdlib.h>//定义结构体
typedef struct
{int age;char name[20];
} Person;int main()
{//创建结构体变量Person p = {20, "John"};//创建指向结构体的指针Person *ptr = &p;//通过指针访问结构体成员printf("Name: %s, Age: %d\n", ptr->name, ptr->age);return 0;
}
4、指针相关问题
4.1 野指针
4.1.1 产生原因
- 指针未初始化:定义指针变量后没有给它赋一个合法的地址值,此时指针指向的位置是随机的,变成野指针。
int* ptr; //ptr就是一个野指针
- 指针所指向的内存被释放后未置空:当使用 free 或 delete 释放了指针所指向的内存后,如果没有将指针设置为 NULL,指针仍然保存着原来已释放内存的地址,就变成了野指针。
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
//此时ptr成为野指针,如果再次访问*ptr就会有问题
- 指针越界操作:当指针进行了不恰当的运算,使其指向了不属于原本所指向的内存区域,也会形成野指针。比如对数组指针进行越界的移动操作。
int main()
{//定义一个包含5个元素的整型数组int arr[5] = {1, 2, 3, 4, 5};//定义一个指针指向数组的首元素int *ptr = arr;//正常访问数组元素for (int i = 0; i < 5; i++) {printf("arr[%d] = %d\n", i, *(ptr + i));}//越界操作:将指针移动到数组范围之外ptr = ptr + 5;//尝试访问越界后的指针指向的内存printf("越界访问的值: %d\n", *ptr);return 0;
}
4.1.2 解决方法
- 初始化指针:在定义指针变量时,将其初始化为 NULL 或者指向一个合法的内存地址。
//法一:初始化为 NULL
int* ptr = NULL;//法二:指向一个合法的内存地址
int num;
int* ptr = #
- 内存释放后置空指针:在使用 free 或 delete 释放内存后,立即将指针赋值为 NULL,这样可以避免再次误操作该指针。
int* ptr = (int*)malloc(sizeof(int));
free(ptr);
ptr = NULL; //释放后置空
- 小心指针运算:进行指针运算时,要确保不超出所指向内存的范围,对于数组指针,要根据数组的大小进行合理的指针移动。
4.2 内存泄漏
4.2.1 动态内存未释放的后果
- 内存浪费:程序占用的内存会不断增加,导致系统可用内存减少,影响其他程序的运行,甚至可能导致系统性能下降。
- 程序崩溃:当系统内存耗尽时,程序可能会因为无法分配到所需的内存而崩溃。
- 资源耗尽:在一些资源有限的环境中,内存泄漏可能会导致系统无法正常工作,因为没有足够的内存来执行其他必要的操作。
4.2.2 解决方法
- 及时释放内存:在使用完动态分配的内存后,要及时使用 free 或 delete 释放内存。
- 使用智能指针(C++):C++ 提供了智能指针(如 std::unique_ptr、std::shared_ptr)来自动管理内存,当智能指针超出作用域时,会自动释放所指向的内存,从而避免内存泄漏。
4.3 指针运算
4.3.1 指针加减整数的运算
指针加减整数的运算结果是一个新的指针,其指向的位置会根据指针所指向的数据类型的大小进行移动。
#include <stdio.h>int main()
{int arr[5] = {1, 2, 3, 4, 5};int *ptr = arr; //ptr指向数组的第一个元素//指针加1int *next_ptr = ptr + 1;printf("ptr 指向的值: %d\n", *ptr); //输出为1printf("ptr + 1 指向的值: %d\n", *next_ptr); //输出为2//指针减1int *prev_ptr = next_ptr - 1;printf("next_ptr - 1 指向的值: %d\n", *prev_ptr); //输出为1return 0;
}
4.3.2 指针间的减法运算
指针的减法运算通常用于计算两个指针之间的距离,结果是一个整数,表示两个指针之间相差的元素个数,前提是这两个指针指向同一块连续的内存区域(如数组)。
#include <stdio.h>int main()
{int arr[5] = {1, 2, 3, 4, 5};int *ptr1 = &arr[0]; //指向数组第一个元素int *ptr2 = &arr[3]; //指向数组第四个元素//计算两个指针之间的距离int distance = ptr2 - ptr1;printf("ptr2 和 ptr1 之间相差的元素个数: %d\n", distance); //输出为3,表示它们之间相差3个int型元素return 0;
}
4.3.3 指针间的比较
只有当两个指针指向同一块连续的内存区域(如数组)且有关联时,进行比较才有意义。例如,比较数组中不同元素的指针,判断它们的先后顺序。
#include <stdio.h>int main()
{int arr[5] = {1, 2, 3, 4, 5};int *ptr1 = &arr[0]; //指向数组第一个元素int *ptr2 = &arr[3]; //指向数组第四个元素//比较指针if (ptr1 < ptr2) {printf("ptr1 指向的元素在 ptr2 指向的元素之前\n");} else {printf("ptr1 指向的元素在 ptr2 指向的元素之后或相同\n");}return 0;
}
4.4 二级指针、三级指针
4.4.1 二级指针
二级指针是指向指针的指针。也就是说,二级指针所存储的地址是一个指针变量的地址,而这个指针变量又指向实际的数据。
4.4.2 三级指针
三级指针是指向二级指针的指针,即它存储的地址是一个二级指针变量的地址。
int num = 10;
int* ptr1 = # //一级指针
int** ptr2 = &ptr1; //二级指针
int*** ptr3 = &ptr2; //三级指针
5、指针数组与数组指针
5.1 指针数组
- 定义:元素为指针的数组
- 语法格式:数据类型* 数组名[数组长度]
#include <stdio.h>int main()
{//定义一个数组a,并给数组赋值int a[10];for (int i = 0; i < 10; i++){a[i] = i + 1;}//指针数组:数组中的每一个元素都是指针int* arr[10] = { a, a + 1, a + 2, a + 3, a + 4, a + 5, a + 6, a + 7, a + 8, a + 9 };//a + 1 == &a[0] + 1 == &a[1];//a[5] ? --> a数组中下标为5的元素是多少?//printf("%d %d", *arr[5], **(arr + 5));//**(arr + 5)的推导//arr == &arr[0];//arr + 5 == &arr[0] + 5 == &arr[5];//*(arr + 5) == *(&arr[5]) == arr[5];//**(arr + 5) == *arr[5] == a[5];return 0;
}
5.2 数组指针
- 定义:指向某个数组的指针
- 语法格式:数据类型 (*指针名) [数组长度]
#include <stdio.h>int main()
{//定义一个数组a,并给数组赋值int a[10];for (int i = 0; i < 10; i++){a[i] = i + 1;}//数组指针:本身是一个指针,存的是元素类型是int、元素个数为10的数组的地址int (*arry)[10];arry = &a; //赋值printf("%d", *((int*)(arry + 1) - 1)); //输出为10return 0;
}
输出语句 printf("%d", *((int*)(arry + 1) - 1)); 的详细解释:
- arry + 1:由于 arry 是一个指向包含 10 个 int 元素数组的指针,arry + 1 会让指针向后移动一个包含 10 个 int 元素数组的长度,也就是跳过整个数组 a 所占用的内存空间,指向数组 a 之后的内存位置。
- (int*):将 arry + 1 的结果强制转换为 int* 类型的指针。这一步的作用是将原本指向整个数组的指针转换为指向单个 int 元素的指针,以便后续进行以 int 为单位的指针运算。
- (int*)(arry + 1) - 1:在强制转换为 int* 类型指针后,进行减 1 操作。因为现在是 int* 类型的指针,减 1 会让指针向前移动一个 int 类型的长度,也就是回到数组 a 的最后一个元素的地址。
- *((int*)(arry + 1) - 1):对前面得到的指针进行解引用操作,获取该指针所指向的内存位置存储的值,也就是数组 a 的最后一个元素的值,即 10。
6、指针函数与函数指针
6.1 指针函数
- 定义:本身是一个函数,返回值是一个指针
- 语法格式:数据类型* 函数名(参数列表)
#include <stdio.h>//指针函数:返回值为指针的函数
//注意:这里返回局部变量的地址会导致未定义行为,因为局部变量在函数结束后会被销毁
//可以使用静态局部变量来解决上述问题int* fun()
{static int a = 10; //使用静态局部变量return &a;
}int main()
{int* ptr = fun();printf("访问返回指针指向的值: %d\n", *ptr);return 0;
}
6.2 函数指针
- 定义:本身是一个指针,存的是函数的地址
- 语法格式:数据类型 (*指针名) (参数列表)
注:“数据类型”指的是函数的返回值类型,“参数列表”指的是函数的参数列表
#include <stdio.h>//函数的定义不允许嵌套
//函数的调用允许嵌套
//当函数体在主函数下方时,需要在函数上方进行函数声明//声明fff函数
int fff();int main()
{//函数指针:本身是一个指针,存的是函数的地址int (*f)() = fff; //fff等价于&fff//函数的调用方式fff();f(); //通过地址访问,fff()等价于f()等价于(*f)()return 0;
}//定义fff函数
int fff()
{printf("asd");return 0;
}
- fff():这是普通的函数调用方式。fff 是函数名,直接在函数名后面加上括号并传入相应的参数( fff 函数没有参数),就可以调用这个函数。当执行 fff() 时,程序会跳转到 fff 函数的代码块中执行其中的语句,即输出字符串 "asd"。
- f():f 是一个函数指针,它存储了函数 fff 的地址。当使用 f() 这种形式调用时,实际上是通过函数指针 f 来调用它所指向的函数(即 fff 函数)。因为 f 指向了 fff 函数的地址,所以 f() 的效果和直接调用 fff() 是一样的,程序同样会跳转到 fff 函数的代码块中执行。
- (*f)():这种写法也是通过函数指针 f 来调用函数。在 C 语言中,函数指针本质上是一个指向函数的地址的指针变量。*f 是对函数指针 f 进行解引用操作,从概念上来说,*f 就表示 fff 函数。所以 (*f)() 同样是调用 f 所指向的函数,它和 f() 以及 fff() 的作用是等价的,最终都会执行 fff 函数中的代码。
相关文章:
基础知识-指针
1、指针的基本概念 1.1 什么是指针 1.1.1 指针的定义 指针是一种特殊的变量,与普通变量存储具体数据不同,它存储的是内存地址。在计算机程序运行时,数据都被存放在内存中,而指针就像是指向这些数据存放位置的 “路标”。通过指针…...
Thymeleaf简介
在Java中,模板引擎可以帮助生成文本输出。常见的模板引擎包括FreeMarker、Velocity和Thymeleaf等 Thymeleaf是一个适用于Web和独立环境的现代服务器端Java模板引擎。 Thymeleaf 和 JSP比较: Thymeleaf目前所作的工作和JSP有相似之处,Thyme…...
ifconfig -bash: ifconfig: command not found
Ubuntu系统安装完成想查看其ip 报错ifconfig -bash: ifconfig: command not found 解决方法 sudo apt update sudo apt install net-tools ip查找成功...
MCP协议量子加密实践:基于QKD的下一代安全通信(2025深度解析版)
一、量子计算威胁的范式转移与MCP协议改造必要性 1.1 传统加密体系的崩塌时间表 根据IBM 2025年量子威胁评估报告,当量子计算机达到4000个逻辑量子比特时(预计2028年实现),现有非对称加密体系将在72小时内被完全破解。工业物联网…...
STM32 基本GPIO控制
目录 GPIO基础知识 编辑IO八种工作模式 固件库实现LED点灯 蜂鸣器 按键基础知识 编辑继电器 震动传感器 433M无线模块 GPIO基础知识 GPIO(General-Purpose input/output,通用输入/输出接口) 用于感知外部信号(输入模式)和控制外部设备&…...
【天外之物】叉乘(向量积)的行列式表示方法
叉乘(向量积)的行列式表示方法如下: 步骤说明: 构造33矩阵: 将三维向量叉乘转换为行列式的形式,需构造一个包含单位向量 i , j , k \mathbf{i}, \mathbf{j}, \mathbf{k} i,j,k 和原向量分量的矩阵&#x…...
北京SMT贴片厂精密制造关键工艺
内容概要 随着电子设备小型化与功能集成化需求日益提升,北京SMT贴片厂在精密制造领域持续突破工艺瓶颈。本文以高密度PCB板贴片全流程为核心,系统梳理从锡膏印刷、元件贴装到回流焊接的关键技术节点,并结合自动化检测与缺陷预防方案…...
服务器架构:SMP、NUMA、MPP及Docker优化指南
文章目录 引言 一、服务器架构基础1. SMP(对称多处理,Symmetric Multiprocessing)2. NUMA(非统一内存访问,Non-Uniform Memory Access)3. MPP(大规模并行处理,Massively Parallel Pr…...
Datawhale春训营赛题分析和总结
1.Datawhale春训营任务一 借助这个云平台,支持类似于这个anaconda相关的交互式的操作,第一个任务就是跑通这个baseline,然后注册账号之后送了对应的相关算力,跑通这个之后需要进行打卡,跑通其实是没问题不大的&#x…...
一键模仿图片风格,图生生APP,实现随时随地“生图自由“
一、什么是"图片模仿"功能? "图片模仿"是图生生AI的功能之一,利用先进的AI技术,分析上传的图片风格、色调、构图等元素,快速生成具有相同风格的图片。无论是产品展示、广告海报还是社交媒体配图,…...
C++——C++11常用语法总结
C11标准由国际标准化组织(ISO)和国际电工委员会(IEC)旗下的C标准委员会(ISO/IEC JTC1/SC22/WG21)于2011年8月12日公布,并于2011年9月出版。2012年2月28日的国际标准草案(N3376)是最接近于C11标准…...
C++17 新特性简解
C17 新特性简解 一、核心语言特性 1. 结构化绑定(Structured Bindings) 用途:解构复合类型(如元组、结构体)为独立变量 示例: #include <iostream> #include <tuple>int main() {// 解构 st…...
【失败】Gnome将默认终端设置为 Kitty
起因 一会儿gnome-terminal一会儿kitty终端,实在是受不了,决定取缔默认的gnome-terminal。 过程 在 Ubuntu 或 Debian 系统上: 确保 Kitty 已经安装。如果未安装,可以在终端中运行命令sudo apt install kitty -y进行安装。 使用系…...
【Easylive】微服务架构在系统中的优缺点的具体体现
【Easylive】项目常见问题解答(自用&持续更新中…) 汇总版 在线视频分享系统项目简介 系统概述 该项目是一个基于SpringCloud微服务架构的在线视频分享系统,主要功能包括: • 用户自主发布视频 • 后台视频审核 • 用户互动…...
锁(Mutex)、信号量(Semaphore)与条件量(Condition Variable)
一、同步机制的核心意义 在多线程/多进程编程中,当多个执行流共享资源(如变量、内存、文件)时,可能因操作顺序不确定导致数据竞争(Data Race)。同步机制的作用是: 保证原子性:确保…...
使用pnpm第一次运行项目报错 ERR_PNPM_NO_PKG_MANIFEST No package.json found in E:\
开始用unibestpnpm写一个小程序 运行pnpm init报错 如标题所示没有package.json这个文件 博主犯了一个很愚蠢的错误。。 准备方案手动创建一个json文件 此时才发现没到根目录下,创建了一个项目之后就没有切入文件夹里。 切入根目录再下载就成功啦...
前沿篇|CAN XL 与 TSN 深度解读
引言 1. CAN XL 标准演进与设计目标 2. CAN XL 物理层与帧格式详解 3. 时间敏感网络 (TSN) 关键技术解析 4. CAN XL + TSN 在自动驾驶领域的典型应用...
从零开始学A2A一:A2A 协议的高级应用与优化
A2A 协议的高级应用与优化 学习目标 掌握 A2A 高级功能 理解多用户支持机制掌握长期任务管理方法学习服务性能优化技巧 理解与 MCP 的差异 分析多智能体场景下的优势掌握不同场景的选择策略 第一部分:多用户支持机制 1. 用户隔离架构 #mermaid-svg-Awx5UVYtqOF…...
追赶地球变化的“快镜头“:遥感时间分辨率的奥秘
在地球表面,万物的生长、兴衰和变迁,如同一部永不停歇的电影。而科学家们想要看清每一帧画面,就必须依赖遥感卫星这个"超级摄影师"。今天,我们就来聊聊遥感领域里一个关键的维度——时间分辨率。 想象一下,如…...
轻量还是全量?Kubernetes ConfigMap 与专业配置中心的抉择
文章目录 简介什么是 ConfigMapConfigMap 的核心能力配置存储与注入动态更新与 Kubernetes 原生生态深度集成 ConfigMap 的固有局限专业配置中心对比选型建议结语 简介 在现代微服务架构中,集中式配置管理是保证应用可维护性、可扩展性和安全性的关键环节。Kuberne…...
mybatis plus打印sql日志到指定目录
1、mybatis plus打印sql日志 参考文档:mybatis plus打印sql日志_mybatisplus日志打印-CSDN博客 2、修改 修改InfoLevelLogger Override public void debug(String s) {// 修改这里logger.info(s);log.debug(s); } 增加:log.debug(s); 修改logback.x…...
CUDAfy的使用
此文章是对一篇使用文档的翻译总结 文档地址 https://www.doczj.com/doc/0f2570173.html CUDAfy使用步骤 1. 环境准备 硬件要求:支持CUDA的NVIDIA显卡(如GTX系列)。软件安装: 安装最新版NVIDIA驱动。下载并安…...
DeepSeek 部署中的常见问题及解决方案
DeepSeek(深度求索)大模型部署过程中常见问题的系统性解决方案,涵盖环境配置、模型加载、性能优化、安全防护及企业级部署等核心场景,结合官方文档与社区实践提供可落地的操作指南: 一、环境配置与依赖问题 1. 操作系统与硬件兼容性 问题表现:部署失败提示驱动不兼容或…...
【AI提示词】儿童看护员
提示说明 儿童看护员旨在帮助用户构建一个既专业又富有爱心的儿童看护员角色,以满足儿童在成长过程中的各种需求。 提示词 # 角色 儿童看护员## 注意 1. 儿童看护员应具备亲和力和耐心,以确保与儿童的良好互动。 2. 专家设计应关注儿童的安全、健康和…...
深入解析 Python 中的装饰器 —— 从基础到实战
1. 装饰器基础 1.1 什么是装饰器? 装饰器本质上是一个 Python 函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能。装饰器的返回值也是一个函数对象。 1.2 语法糖: 符号 Python 提供了 符号作为装饰器的语法糖,…...
学习海康VisionMaster之中线查找
一:进一步学习了 今天学习下VisionMaster中的中线查找,这个就是字面意思,输入两条直线,输出两条直线的中线 二:开始学习 1:什么是中线查找?今天这个比较简单,其实这个模块算是一个几…...
笔记整理五
STP生成树 stp生成树是用于解决二层环路问题的协议。 二层环路为有以下三种: 1.广播风暴 2.MAC地址的偏移(每一次循环,都会导致交换机来回刷新MAC地址表记录) 3.多帧复制 stp生成树:需要将原本的环型拓扑结构转换…...
js实现的前端水印
效果 var defaultConfig {content: [], // 水印内容数组fontSize: 14, // 字体大小(px)fontFamily: sans-serif, // 字体color: rgba(255, 255, 255,.3), // 字体颜色rotate: -20, // 旋转角度(度数)zIndex: 2147483647, // 层级globalAlpha: 0.5, // 透明度canvasWidth: 30…...
前端服务器部署报错记录
报错1:Refused to apply style from http://xxxxxxx.online/assets/index.DepkYCYv.css because its MIME type (text/plain) is not a supported stylesheet MIME type, and strict MIME checking is enabled. index-Dnq3oQAv.js:1 解释:浏览器期望加载…...
JAVA中多线程的经典案例
文章目录 一、线程安全的单例模式(一)饿汉模式(二)懒汉模式 二、阻塞队列(一)生产者消费者模型(二)阻塞队列(三)自定义阻塞队列 三、定时器(一&am…...
国产三维CAD皇冠CAD(CrownCAD)在「轨道交通行业」建模教程:轨道列车
在轨道交通行业,复杂系统集成、大规模装配验证与跨地域协同设计始终是核心痛点。传统设计工具难以应对动辄百万级零部件的装配挑战,且数据孤岛、版本混乱、硬件成本高昂等问题长期制约行业数字化转型。皇冠CAD(CrownCAD)作为国产云…...
Linux 日常运维命令大全
Linux 作为一种开源操作系统,在服务器运维中扮演着重要角色。掌握常用的 Linux 命令对于运维人员而言至关重要。本文将整理一份 Linux 服务器运维常用命令大全,帮助你在日常工作中提高效率和准确性。 1. 基础命令 基础命令是Linux操作的起点࿰…...
安全测试报告模板
安全测试报告 一、项目概况 项目名称XX智慧医疗平台被测系统版本V2.3.1测试类型渗透测试漏洞扫描测试时间2024年2月15-20日测试标准OWASP TOP 10 2021 二、测试环境 生产环境镜像: - 服务器:CentOS 7.9 Tomcat 9 - 数据库:MySQL 8.0集群…...
树莓派超全系列教程文档--(31)config.txt常用选项介绍
config.txt常用选项介绍 常用选项常用显示选项hdmi_enable_4kp60 常用硬件配置选项camera_auto_detectdisplay_auto_detectdtoverlaydtparamarm_boostpower_force_3v3_pwm 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 常用选项 常用显示选项 …...
算法-堆+单调栈
堆 首先堆在我们的Java中我们的是一个优先队列类 PriorityQueue 然后我们要弄最大堆和最小堆 最大堆: PriorityQueue<Integer> pq new PriorityQueue<Integer>((a, b) -> b - a); 最小堆: PriorityQueue<Integer> pq new P…...
Charles破解 激活码 Java
第一步,下载charles Download a Free Trial of Charles • Charles Web Debugging Proxy 第二部,生成key,这里使用的是java代码 import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Random;public class test {private static final int ROUNDS 12;p…...
线上蓝桥杯比赛环境配置
1.编译环境(以下是JAVA示例) Java软件开发编程环境 链接: https://pan.baidu.com/s/1JRNx0bkgHmPqQhANSFBNkQ 提取码: ftgw 下载对应的编译器和jdk以及对应的API文档 解压后把eclipse发送到桌面方便使用 2.录屏软件,我这边选择的是OBS St…...
民办生从零学C的第十一天:操作符
每日励志:我们可以随时的转身,但是决不能后退。 一.操作符的分类 算术操作符:、-、*、/、% 移位操作符:<<、>> 位操作符:&、|、^ 赋值操作符:、、-、*、/、%、<<、>>、&…...
疑难问题解决(2)
(1):在k230开发板中,ubuntu操作系统中的文件夹中的k230_sdk文件夹与canmv_k230文件夹的区别,以及 /home/ubuntu/canmv_k230/src/rtsmart/rtsmart/userapps/07_driver_hello 与 /home/ubuntu/k230_sdk/src/big/rt-smart…...
第六章 进阶04 尊重
本周周会给大家讲的议题是:尊重。 用“尊重”给周报文件冠名,周会中打开这个文件,就可以在标题中醒目地看到,加深了大家的印象、勾起了大家的好奇心。坚持长期事项的同时,偶尔也灵光一现给团队管理加入一些小插曲&…...
Android 12.0 framework实现对系统语言切换的功能实现
1.前言 在12.0的系统rom定制化开发过程中,在定制某些接口的过程中,需要通过系统提供接口,然后实现对系统语言的切换 功能实现,接下来分析下系统中关于系统语言切换的相关功能 2.framework实现对系统语言切换的功能实现的核心类 frameworks/base/core/java/android/app/IA…...
Origin LabTalk
之前用惯了matplotlib绘图,出于科研需要部分图用origin来画,但是还是想着要结合python来处理数据更加的方便,经过一番捣鼓发现origin自带有labtalk,并且还带有python的环境,真可谓是NB的很。 若能由程序代劳,何必亲手?…...
基于VS Code 为核心平台的python语言智能体开发平台搭建
以下是基于 VS Code 为核心平台,整合 Node-RED、Gradio、Docker Desktop 的智能体可视化开发平台优化方案,聚焦工具链深度集成与开发效率提升: 一、核心架构设计 #mermaid-svg-f8l9kYPAlJ2TlpGF {font-family:"trebuchet ms",verd…...
Python 创意:AI 图像生成
一、基于 Stable Diffusion 的本地创意创作 Stable Diffusion 是开源图像生成模型的代表,通过 Python 结合diffusers库,可实现本地图像生成。 1. 环境搭建 首先,安装必要的库: pip install diffusers transformers torch若使用 GPU 加速,需安装对应版本的 CUDA 和 cuD…...
vue3 传参 传入变量名
背景: 需求是:在vue框架中,接口传参我们需要穿“变量名”,而不是字符串 通俗点说法是:在网络接口请求的时候,要传属性名 效果展示: vue2核心代码: this[_keyParam] vue3核心代码&…...
Skipped breakpoint at ... because of stepping in another thread问题分析
在Java多线程应用程序的调试过程中,开发者可能会遇到“Skipped breakpoint at … because of stepping in another thread”这样的提示。这通常是因为调试器在处理多线程操作时,忽略了某个断点。本文将详细分析这一问题的原因,并提供有效的解…...
MATLAB脚本实现了一个转子系统的参数扫描和分岔分析
% 参数扫描范围 clc; clear; close all;S_values 500:200:20000; % 转速范围% 定义系统参数 N 5; % 质量点数量 num_nodes N; % 节点数 num_dofs_per_node 4; % 每个节点的自由度数 num_elements num_nodes-1; % 单元数 total_dofs num_nodes * num_dofs_per_node; % 总自…...
基于Flask的AI工具聚合平台技术解析
基于Flask的AI工具聚合平台技术解析 一、项目架构设计 本系统采用经典的三层架构模式,通过Mermaid架构图可清晰看到数据流向: 用户请求通过浏览器发送至Flask服务器路由系统解析请求路径模板引擎动态渲染页面静态资源提供样式支持独立数据模块实现内容…...
AUTOSAR图解==>AUTOSAR_SWS_CryptoInterface
AUTOSAR 加密接口(Crypto Interface)详解 基于AUTOSAR标准4.4.0的加密接口规范详细分析与图解 目录 概述 1.1 加密接口的作用与位置 1.2 主要术语解释架构设计 2.1 加密接口架构 2.2 组件关系内部结构 3.1 类结构 3.2 配置项运行流程 4.1 加密请求处理流程 4.2 同步与异步处理…...
GCD算法的学习
GCD算法的学习 学习了前辈wzx15927662183的文章GCD算法精讲-CSDN博客 介绍 GCD通常用来求两个数的最大公约数 算法的核心:gcd(a,b) gcd(b,a % b) 证明的思路: 证明 gcd(a, b) gcd(b, a % b) 的思路: 设 a > b 1. 构造 a % b : 设 …...