指针(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 = #
2,里&
是取地址运算符,它获取变量num的内存地址,并将其赋值给指针p
,此时p就指向了变量num。也可以先定义指针,再进行赋
int num = 10;
int *p;
p = #
3,这是最安全的初始化方式之一,将指针初始化位null(空指针),表示指针不知想任何有效的内存地址。null是一个特殊的指针值,通常定义位0。
int* p = NULL; // 初始化为NULLif(p == NULL) {printf("p是NULL\n");}
4,通过动态内存分配函数(如malloc、calloc
、realloc
)分配内存,并将指针初始化为分配的内存地址。这种方式适用于需要在运行时动态分配内存的场景(仅展示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,注意事项(必看)
- 内存管理:当函数返回指针时,要确保返回的指针指向有效的内存区域,并且在不再使用时及时释放动态分配的内存,防止内存泄漏。
- 空指针检查:在使用函数返回的指针或函数指针之前,最好进行空指针检查,避免对空指针进行操作导致程序崩溃。
- 函数指针类型匹配:函数指针的类型必须与所指向的函数的返回类型和参数列表完全匹配,否则会导致编译错误或未定义行为。
九,多级指针
多级指针,也就是指针的指针,在 C 语言里是一个较为高级且强大的特性。下面会从多级指针的定义、初始化、使用场景、注意事项等方面进行详细介绍。
1. 多级指针的定义与初始化
1,定义
多级指针是指指向指针的指针,常见的有二级指针、三级指针等。
数据类型 *指针变量名; //一级指针
数据类型 **指针变量名; //二级指针
数据类型 ***指针变量名; //三级指针
2,初始化
多级指针的初始化需要关联到一个已存在的指针。
#include <stdio.h>
int main()
{int num = 10;int *p = #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. 多级指针的注意事项
-
内存管理:当使用多级指针进行动态内存分配时,必须注意内存的分配和释放顺序。一般来说,要先释放内层指针指向的内存,再释放外层指针指向的内存,避免内存泄漏。例如在上面动态二维数组的例子中,要先释放每一行的内存,再释放存储行指针的内存。
-
查空指针检:在使用多级指针之前,要进行空指针检查,防止对空指针进行解引用操作,从而避免程序崩溃。比如在分配内存时,如果返回
NULL
,就需要进行错误处理。 -
理解解引用操作:多级指针涉及多次解引用操作,要清楚每次解引用所访问的对象。例如,二级指针
**pp
需要两次解引用才能访问到最终的数据,理解这个过程有助于正确使用多级指针。
相关文章:
指针(C语言)从0到1掌握指针,为后续学习c++打下基础
目录 一,指针 二,内存地址和指针 1,什么是内存地址 2,指针在不同系统下所占内存 三,指针的声明和初始化以及类型 1,指针的声明 2,指针 的初始化 1, 初始化方式优点及适用场景 4,指针的声明初始化类型…...
php接口连接数据库
框架:https://www.thinkphp.cn/doc 创建网站 域名自己写 创建文件夹,“test”拉取框架,地址栏输入 composer create-project topthink/think5.1.* tp5 会自动创建一个tp5文件夹 根目录选择刚刚创建拉框架的文件夹 以test为示例 “D:\test\…...
Qt中json的使用
目录 一、json相关类和接口 1.QJsonDocument 2.QJsonObject 3.QJsonArray 4.QJsonValue 二、json写文件 1.写文件基本流程 2.代码示例 三、json读文件 1.读文件基本流程 2.代码示例 json是一种轻量级的数据交换格式,在Qt中使用json数据可以通过Qt提供的Q…...
OpenAI-Edge-TTS:本地化 OpenAI 兼容的文本转语音 API,免费高效!
文本转语音(TTS)技术已经成为人工智能领域的重要一环,无论是语音助手、教育内容生成,还是音频文章创作,TTS 工具都能显著提高效率。今天要为大家介绍的是 OpenAI-Edge-TTS,一款基于 Microsoft Edge 在线文本…...
物业系统改革引领行业智能化管理与提升服务质量的新征程
内容概要 在当今迅速变化的社会中,物业系统改革正在悄然推动行业的智能化管理进程。物业管理作为一个古老而传统的领域,面临着诸多挑战,包括效率低下、业主需求难以满足等。数字化转型为这一现象注入了新活力,帮助物业公司通过先…...
【LLM】Deepseek本地部署学习
文章目录 1. 访问ollama官网安装平台2. 选择配置3. 下载和运行 1. 访问ollama官网安装平台 https://ollama.com/ 2. 选择配置 参考以下配置要求 3. 下载和运行 ollama run deepseek-r1:7b...
Vscode编辑器下 Markdown无法显示图片
1.问题 在vscode 编辑器中无法预览 markdon 文件中的图片 2.解决方案 大部分出现这种情况是因为新版本的vscode会阻拦有风险的资源显示,将安全等级调低即可。 方式一: 1.打开任意 MD 文件,ctrl,调出设置 2. 输入 markdown.ch…...
Java实现.env文件读取敏感数据
文章目录 1.common-env-starter模块1.目录结构2.DotenvEnvironmentPostProcessor.java 在${xxx}解析之前执行,提前读取配置3.EnvProperties.java 这里的path只是为了代码提示4.EnvAutoConfiguration.java Env模块自动配置类5.spring.factories 自动配置和注册Enviro…...
高效学习方法分享
高效学习方法分享 引言 在信息高速发展的今天,学习已经成为每个人不可或缺的一部分。你是否曾感到学习的疲惫,信息的爆炸让你无从下手?今天,我们将探讨几种高效的学习方法,帮助你从中找到适合自己的学习之道。关于学…...
分库分表 相关问题
问题:分库后,就有多个数据源需要,dbproxy 对机器做代理,一般需要lvs/f5 等手段来实现流量的负载均衡,跨机房可能需要dns分发,例如 mycat 阿里的主键。 就这个问题通过一问一答的方式解答 什么是 dbproxy&…...
【Linux系统】进程间通信:实现命名管道通信
认识命名管道通信 命名管道通信的结构图示: 图中的 Server 和 Client 是不同的进程, Server 负责发送数据, Client 则是接收数据,进程之间通过命名管道进行数据通信 准备工作: 创建以下文件 Server.hpp #服务器类的…...
IT服务管理平台(ITSM):构建高效运维体系的基石
IT服务管理平台(ITSM):构建高效运维体系的基石 在数字化转型浪潮的推动下,企业对IT服务的依赖日益加深,如何高效管理和优化IT服务成为企业面临的重要课题。IT服务管理平台(ITSM)应运而生,以其系统化的管理方法和工具,助力企业实现IT服务的规范化、高效化和智能化。本…...
SSM开发(八) MyBatis解决方法重载
目录 一、Mybatis能否支持方法重载? 二、解决 MyBatis 方法重载问题的几种方法 解决方法一: (注解方式) 将重载方法命名为不同的方法名 解决方法二:采用@SelectProvider注解 解决方法三:使用 MyBatis 的 标签和动态 SQL 来构建不同参数的 SQL 查询 三、总结 一、Myb…...
AIGC时代的Vue或React前端开发
在AIGC(人工智能生成内容)时代,Vue开发正经历着深刻的变革。以下是对AIGC时代Vue开发的详细分析: 一、AIGC技术对Vue开发的影响 代码生成与自动化 AIGC技术使得开发者能够借助智能工具快速生成和优化Vue代码。例如,通…...
【实践案例】使用Dify构建文章生成工作流【在线搜索+封面图片生成+内容标题生成】
文章目录 概述开始节点图片封面生成关键词实时搜索主题参考生成文章详情和生成文章标题测试完整工作流运行测试结果 概述 使用Dify构建文章生成工作流,使用工具包括:使用 Tavily 执行的搜索查询,使用Flux生成封面图片,使用Stable…...
使用 Context API 管理临时状态,避免 Redux/Zustand 的持久化陷阱
在开发 React Native 应用时,我们经常需要管理全局状态,比如用户信息、主题设置、网络状态等。而对于某些临时状态,例如 数据同步进行中的状态 (isSyncing),我们应该选择什么方式来管理它? 在项目开发过程中ÿ…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.26 统计圣殿:从描述统计到推断检验
1.26 统计圣殿:从描述统计到推断检验 目录 #mermaid-svg-3nz11PRr47fVfGWZ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3nz11PRr47fVfGWZ .error-icon{fill:#552222;}#mermaid-svg-3nz11PRr47fVfGWZ…...
C# 添加、替换、提取、或删除Excel中的图片
在Excel中插入与数据相关的图片,能将关键数据或信息以更直观的方式呈现出来,使文档更加美观。此外,对于已有图片,你有事可能需要更新图片以确保信息的准确性,或者将Excel 中的图片单独保存,用于资料归档、备…...
商密测评题库详解:商用密码应用安全性评估从业人员考核题库详细解析(9)
1. 申请商用密码测评机构需提交材料考点 根据《商用密码应用安全性测评机构管理办法(试行)》,申请成为商用密码应用安全性测评机构的单位应当提交的材料不包括( )。 A. 从事与普通密码相关工作情况的说明 B. 开展测评工作所需的软硬件及其他服务保障设施配备情况 C. 管…...
开源项目Umami网站统计MySQL8.0版本Docker+Linux安装部署教程
Umami是什么? Umami是一个开源项目,简单、快速、专注用户隐私的网站统计项目。 下面来介绍如何本地安装部署Umami项目,进行你的网站统计接入。特别对于首次使用docker的萌新有非常好的指导、参考和帮助作用。 Umami的github和docker镜像地…...
模型I/O功能之模型包装器
文章目录 模型包装器分类LLM模型包装器、聊天模型包装器 截至2023年7月,LangChain支持的大语言模型已经超过了50种,这其中包括了来自OpenAI、Meta、Google等顶尖科技公司的大语言模型,以及各类优秀的开源大语言模型。对于这些大语言模型&…...
免杀国内主流杀软的恶意样本分析
目录下存在愤怒的小鸟.exe和fun.dll文件,最新版火绒,windows defender,腾讯电脑管家,360静态扫描都未发现恶意程序 动态执行,杀软也未拦截 上传到virustotal网站分析恶意程序,只有三个引擎检测出来 die分析…...
Cloudreve:Star22.3k,免费开源的网盘,支持多种存储方式,它允许用户快速搭建个人或团队的私有云存储服务。
嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 Cloudreve是一个基于Web的文件管理和分享系统,它允许用户快速搭建个人或团队的私有云存储服务。该项目以其高度的可定制性和灵活性&#x…...
【高内聚】设计模式是如何让软件更好做到高内聚的?
高内聚(High Cohesion)是指模块内部的元素紧密协作,共同完成一个明确且相对独立的功能。就像高效的小团队,成员们目标一致,相互配合默契。 低耦合(Loose Coupling)是指模块之间的依赖较少&#…...
第一个3D程序!
运行效果 CPP #include <iostream> #include <fstream> #include <string> #include <cmath>#include <GL/glew.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/type_ptr.hpp> #include <glm/gtc/…...
基础项目实战——学生管理系统(c++)
目录 前言一、功能菜单界面二、类与结构体的实现三、录入学生信息四、删除学生信息五、更改学生信息六、查找学生信息七、统计学生人数八、保存学生信息九、读取学生信息十、打印所有学生信息十一、退出系统十二、文件拆分结语 前言 这一期我们来一起学习我们在大学做过的课程…...
【PyTorch】6.张量形状操作:在深度学习的 “魔方” 里,玩转张量形状
目录 1. reshape 函数的用法 2. transpose 和 permute 函数的使用 4. squeeze 和 unsqueeze 函数的用法 5. 小节 个人主页:Icomi 专栏地址:PyTorch入门 在深度学习蓬勃发展的当下,PyTorch 是不可或缺的工具。它作为强大的深度学习框架&am…...
OpenEuler学习笔记(十六):搭建postgresql高可用数据库环境
以下是在OpenEuler系统上搭建PostgreSQL高可用数据环境的一般步骤,通常可以使用流复制(Streaming Replication)或基于Patroni等工具来实现高可用,以下以流复制为例: 安装PostgreSQL 配置软件源:可以使用O…...
记录一次Sqoop从MySQL导入数据到Hive问题的排查经过
个人博客地址:记录一次Sqoop从MySQL导入数据到Hive问题的排查经过 | 一张假钞的真实世界 问题描述 MySQL中原始数据有790W+的记录数,在Sqoop抽取作业成功的情况下在Hive中只有500W左右的记录数。 排查过程 数据导入脚本Log 通过Log可以发现以下信息: 该Sqoop任务被分解…...
什么是集成学习
什么是集成学习 集成学习是一种分布式机器学习框架,通过构建多个学习器并将其结合起来完成学习任务。由于在实际应用中单一的学习器往往不能达到理想的学习效果,且有时单一学习器会导致过拟合,因此使用多个学习器进行集成学习往往能够达到更好…...
VSCode+Continue实现AI辅助编程
Continue是一款功能强大的AI辅助编程插件,可连接多种大模型,支持代码设计优化、错误修正、自动补全、注释编写等功能,助力开发人员提高工作效率与代码质量。以下是其安装和使用方法: 一、安装VSCode 参见: vscode安…...
Springboot如何使用面向切面编程AOP?
Springboot如何使用面向切面编程AOP? 在 Spring Boot 中使用面向切面编程(AOP)非常简单,Spring Boot 提供了对 AOP 的自动配置支持。以下是详细的步骤和示例,帮助你快速上手 Spring Boot 中的 AOP。 1. 添加依赖 首先ÿ…...
ThreadLocal源码解析
文章目录 一、概述二、get()方法三、set()方法四、可能导致的内存泄漏问题五、remove六、思考:为什么要将ThreadLocalMap的value设置为强引用? 一、概述 ThreadLocal是线程私有的,独立初始化的变量副本。存放在和线程进行绑定的ThreadLocalMa…...
Maven的单元测试
1. 单元测试的基本概念 单元测试(Unit Testing) 是一种软件测试方法,专注于测试程序中的最小可测试单元——通常是单个类或方法。通过单元测试,可以确保每个模块按预期工作,从而提高代码的质量和可靠性。 2.安装和配…...
深度学习 Pytorch 深层神经网络
在之前已经学习了三种单层神经网络,分别为实现线性方程的回归网络,实现二分类的逻辑回归(二分类网络),以及实现多分类的softmax回归(多分类网络)。从本节开始,我们将从单层神经网络展…...
【python】三帧差法实现运动目标检测
三帧差法是一种常用的运动目标检测方法,它通过比较连续三帧图像之间的差异来检测运动物体。这种方法尤其适用于背景变化较小的场景。 目录 1 方案 2 实践 ① 代码 ② 效果图 1 方案 具体步骤如下: ① 读取视频流:使用cv2.VideoCapture()…...
机器人抓取与操作经典规划算法(深蓝)——2
1 经典规划算法 位姿估计:(1)相机系位姿 (2)机器人系位姿 抓取位姿:(1)抓取位姿计算 (2)抓取评估和优化 路径规划:(1)笛卡…...
WGCLOUD服务器资源监控软件使用笔记 - Token is error是什么错误
[wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:90: 主机监控信息上报server开始 [wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:99: 主机监控信息上报server返回信息: {"result":"Token is error"} 这个错误是因为agent配置的wgToken和serv…...
在排序数组中查找元素的第一个和最后一个位置(力扣)
一.题目介绍 二.题目解析 使用二分进行查找 2.1处理边界情况 如果数组为空,直接返回 [-1, -1],因为无法找到目标值。 int[] ret new int[2]; ret[0] ret[1] -1; if (nums.length 0) return ret; 2.2查找左端点(目标值开始位置&#…...
Kafka的消息协议
引言 在学习MQTT消息协议的时候我常常思考kafka的消息协议是什么,怎么保证消息的可靠性和高性能传输的,接下来我们一同探究一下 Kafka 在不同的使用场景和组件交互中用到了多种协议,以下为你详细介绍: 内部通信协议 Kafka 使用…...
Vue 3 30天精进之旅:Day 09 - 组合式API
在Vue 3中,组合式API(Composition API)是一个引入的新特性,它为开发者提供了一种更灵活的方式来构建和组织组件。与传统的选项API相比,组合式API更注重逻辑的复用和逻辑的组合,让我们更容易处理大型应用中的…...
Day28(补)-【AI思考】-AI会不会考虑自己的需求?
文章目录 AI会不会考虑自己的需求?一、**技术本质:深度≠理解**二、**传播机制:热搜如何制造幻觉**三、**伦理考量:为何必须"撇清"**关键结论 AI会不会考虑自己的需求? 让思想碎片重焕生机的灵魂:…...
JavaScript 进阶(下)
原型 what 首先,构造函数通过原型分配的函数是所有对象所 共享的。 然后,JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象 这个对象可以挂载函数,对象实…...
selenium自动化测试框架——面试题整理
目录 1. 什么是 Selenium?它的工作原理是什么? 2. Selenium 主要组件 3. 常见 WebDriver 驱动 4. Selenium 如何驱动浏览器? 5. WebDriver 协议是什么? 6. Page Object 模式与 Page Factory 7. 如何判断元素是否可见&#x…...
CF1098F Ж-function
【题意】 给你一个字符串 s s s,每次询问给你 l , r l, r l,r,让你输出 s s s l , r sss_{l,r} sssl,r中 ∑ i 1 r − l 1 L C P ( s s i , s s 1 ) \sum_{i1}^{r-l1}LCP(ss_i,ss_1) ∑i1r−l1LCP(ssi,ss1)。 【思路】 和前一道题一样&#…...
数据库备份、主从、集群等配置
数据库备份、主从、集群等配置 1 MySQL1.1 docker安装MySQL1.2 主从复制1.2.1 主节点配置1.2.2 从节点配置1.2.3 创建用于主从同步的用户1.2.4 开启主从同步1.2.4 主从同步验证 1.3 主从切换1.3.1 主节点设置只读(在192.168.1.151上操作)1.3.2 检查主从数…...
电脑要使用cuda需要进行什么配置
在电脑上使用CUDA(NVIDIA的并行计算平台和API),需要进行以下配置和准备: 1. 检查NVIDIA显卡支持 确保你的电脑拥有支持CUDA的NVIDIA显卡。 可以在NVIDIA官方CUDA支持显卡列表中查看显卡型号是否支持CUDA。 2. 安装NVIDIA显卡驱动…...
【Unity3D】实现横版2D游戏——攀爬绳索(简易版)
目录 GeneRope.cs 场景绳索生成类 HeroColliderController.cs 控制角色与单向平台是否忽略碰撞 HeroClampController.cs 控制角色攀爬 OnTriggerEnter2D方法 OnTriggerStay2D方法 OnTriggerExit2D方法 Update方法 开始攀爬 结束攀爬 Sensor_HeroKnight.cs 角色触发器…...
JS 时间格式大全(含大量示例)
在 JS 中,处理时间和日期是常见的需求。无论是展示当前时间、格式化日期字符串,还是进行时间计算,JavaScript 都提供了丰富的 API 来满足这些需求。本文将详细介绍如何使用 JavaScript 生成各种时间格式,从基础到高级,…...
opencv裁剪视频区域
import cv2 # 打开视频文件 video_path input.mp4 cap cv2.VideoCapture(video_path) # 获取视频的帧率、宽度和高度 fps int(cap.get(cv2.CAP_PROP_FPS)) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 定义裁剪区…...