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

初始C语言(7)——详细讲解有关初阶指针的内容

系列文章目录

 第一章 “C“浒传——初识C语言(1)(更适合初学者体质哦!)

 第二章 初始C语言(2)——详细认识分支语句和循环语句以及他们的易错点 

 第三章 初阶C语言(3)——特别详细地介绍函数 

 第四章 初始C语言(4)——详细地讲解数组的内容以及易错点 

 第五章 初始C语言(5)——详细讲解操作符以及操作符的易错点  

 第六章 初始C语言(6)——详细讲解表达式求值以及其易错点 

 第七章 初始C语言(7)——详细讲解有关初阶指针的内容


目录

系列文章目录

前言

一、指针是什么?

1.1 指针 

总结:指针就是地址,口语中受到指针通常是指针变量。 

1.2 指针变量

1.3 内存

1.2.1 什么是内存: 

1.2.2 内存的抽象模型:

二、指针和指针类型

2.1 指针的解引用

2.2 指针 +- 整数

2.3 指针类型的应用

三、野指针

3.1 野指针成因 

3.2 如何规避野指针 

3.2.1 指针初始化要注意两个点 

3.2.2 指针使用之前要检查有效性

悬空指针

四、指针运算

4.1 指针 +- 整数

4.2 指针 - 指针

4.3 指针的关系运算

五、指针和数组

六、二级指针

七、指针数组

总结


前言

       在上一章内,小编带领大家详细学习了有关表达式求值的相关内容,学习了隐式类型转换和显式类型转换的相关内容介绍了操作符的一些属性

       而在这一章内,小编要带领大家进行学习初阶指针的一些内容,不要害怕,这一部分只是为了后面讲述进阶指针做一个铺垫,所以不要担心指针这一节很难,当你刚开始就害怕的话,你将永远地活在这个阴影之下,会永远学不会这一章的内容,希望大家能够有耐心地将这一章看完!


一、指针是什么?

       说起指针,小编当年也是比较害怕的,因为指针算的上是C语言中很难的一个知识点,但是一般写代码的时候也不常用,导致很多人不是非常重视,所以请认真学习一下这一节,刚开始先讲一下之前讲过的东西。

指针理解的两个要点

  1. 指针是内存中一个最小单元的编号,也就是地址
  2. 平时口语中说的指针,通常指的是指针变量,是用来存放地址的变量

1.1 指针 

  • 指针是C语言非常重要的特征,指针也是一种变量,只不过它所表示的不是数据的值,而是内存的地址。
  • 通过使用指针,可以对任意(非绝对)内存地址的数据进行读写。
  • 在了解指针读写的过程前,我们先需要了解如何定义一个指针,和普通的变量不同,在定义指针时,我们通常会在变量名前加一个*号。

       我们以32位计算机为例,32位计算机的内存地址是4个字节,在这种情况下,指针的长度也是32位。下面会讲解32位计算机的地址线。

总结:指针就是地址,口语中受到指针通常是指针变量。 

       在上面总结中有两个名词:内存指针变量。 我们先来认识一下指针变量,再来认识一下内存。

1.2 指针变量

       在前面初始C语言(5)——详细讲解操作符以及操作符的易错点我们学过一个操作符 & ,我们可以通过 & (取地址操作符)取出变量的内存其实就是地址,把地址可以存放在一个变量中,这个变量就是指针变量。在了解指针读写的过程前,我们先需要了解如何定义一个指针,和普通的变量不同,在定义指针时,我们通常会在变量名前加一个 *

int main()
{int a = 0x11223344; //在内存中开辟一个空间int* p = &a;//这里我们对变量a,取出他的地址//a变量占用4个字节的空间,这里是将a的4个字节的第一个字节的地址存放在p变量中,p是一个指针变量。return 0;
}

总结:指针变量就是用来存放地址的变量。(存放在指针中的值都被当成地址处理) 

1.3 内存

       可能大家对内存的理解都不是很到位,在这里小编将要带领大家进行深一步学习,大家先记住一句话就是:内存和存储空间不是一回事。(更加详细地请看内存)

1.2.1 什么是内存: 

  • 内存是计算机中的重要部件,也称内存储器和主存储器,它是程序和CPU进行沟通的桥梁
  • 计算机中所有程序的运行都在内存中进行它用于暂时存放CPU中的运算数据以及与硬盘等外部存储器交换的数据内存性能的强弱影响计算机整体发挥的水平
  • 只要计算机开始运行,操作系统就会把需要运算的数据从内存调到CPU中进行运算,当运算完成,CPU将结果传送出来。

  

1.2.2 内存的抽象模型:

       为了方便大家记住,我们把内存模型映射成为我们现实生活中的模型,内存的模型是一层一层的,在现实生活中,其很像我们生活中的高楼大厦。

       在这个高楼大厦中,一层可以存储一个字节的数据楼层号就是地址,下面是内存和楼层整合的模型图。

  • 我们知道程序中的数据不仅只有数值,还有数据类型的概念 ,从内存上看就是占用内存大小(占用楼层数)的意思。
  • 即使物理上强制以1个字节为单位来逐一读写数据的内存,在程序中,通过指定其数据类型,也能实现以特定字节数为单位来进行读写。

在上面的讲解中也会有一些问题:

  • 一个小的单元到底是多大?(一个字节)
  • 如何编址?

       我们先来回答第一个问题:经过仔细地计算和权衡会发现一个字节给一个对应的地址是比较合适的。因为最小的数据类型是char,其单位为一个字节。如果过小,不好存储数字;如果过大,又很浪费空间。   

       那么回答第二个问题: 对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)低水平(低电压)就是(1或者0);那么32根地址线产生的地址就会是:

00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000001

00000000 00000000 00000000 00000002

......

11111111   11111111   11111111   11111111

       这里就有2的32次方个地址,每一个地址表示一个字节。那我们就可以给(2^32byte == 2^32/1024KB ==  2^32/1024/1024MB == 2^32/1024/1024/1024GB == 4GB)4G的空间进行编址。同样的方法,那64位机器如果给64根地址线,那能编址多大空间?答案是16G的空间

但这里我们应该明白:

  • 在32位机器上,地址是32个0或者1组成的二进制序列,那地址就要用4个字节(一个字节是8个byte)的空间进行存储,所以一个字节变量的大小就应该是4个字节。
  • 那如果是在64位机器上,如果有64个地址线,那一个字节变量的大小是8个字节,才能存放一个地址。

总结:

  • 指针是用来存放地址的,地址是唯一标识一块地址空间的。
  • 指针的大小在32位平台是4个字节,在64位平台上是8个字节

二、指针和指针类型

       在之前,我们学习变量时,会根据现实生活提供不同的类型:整形,浮点型等……那么指针有没有类型呢?准确地说:有的。

当有这样的代码:

int num = 10;
p = #

       我们要将 &num(num的地址)保存到p中,我们知道p是一个指针变量,那么它的类型是什么呢?我们要给指针变量相应的类型。

char*   pc = NULL;
int*    pc = NULL;
short*  pc = NULL;
long*   pc = NULL;
float*  pc = NULL;
double* pc = NULL;

这里可以看到,指针的定义方式是:type + *

其实:

  • char* 类型的指针是为了存放 char 类型变量的地址;
  • short* 类型的指针是为了存放 short 类型变量的地址;
  • int* 类型的指针是为了存放 int 类型变量的地址。

       那为什么要这么麻烦?指针变量的大小不是都是4或者8个字节吗?那指针类型的意义是什么?请看下面进行讲解: 

2.1 指针的解引用

#include <stdio.h>
int main()
{int n = 0x11223344;char* pc = (char*)&n; //为了消除警告int* pi = &n;*pc = 0;//重点在调试的过程中观察内存的变化*pi = 0;//重点在调试的过程中观察内存的变化return 0;
}

在调试过程中,我们可以发现,指针类型是有意义的,指针类型决定了指针进行解引用操作时,访问几个字节。

总结:

       指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。比如:char* 的指针解引用就只能访问一个字节,而 int* 的指针解引用就能访问四个字节

       经过上面的学习,有些人可能要疑惑,为什么不自动识别传来的地址是什么类别的呢? 其实是已经识别了。

  

2.2 指针 +- 整数

#include <stdio.h>
int main()
{int n = 10;char* pc = (char*)&n;int* pi = &n;printf("%p\n", &n);printf("%p\n", pc);printf("%p\n", pc + 1);printf("%p\n", pi);printf("%p\n", pi + 1);return 0;
}

为什么这两个指针跳过的大小不同呢?

 首先,这两个指针的类型是不一样的;

其次,整形类型指针指向的是一个整形的对象;字符类型指针指向的是一个字符的对象。

总结:

       指针的类型决定了指针向前或者向后走一步跳过几个字节(距离)。 比如:一个 char* 的指针加1跳过一个字节,一个 int* 的指针加1跳过4个字节。

2.3 指针类型的应用


三、野指针

       野指针,顾名思义就是不确定的指针,大家可以用野人来类比。概念:野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的) 

说明:指针变量也是变量,在前面我们知道如果变量不初始化,在内存中会存放随机值(全局变量不初始化,存放0,局部变量不初始化,存放随机值)。同理指针变量如果赋给随机值是没有意义的,会成为野指针的。随机值会导致指针无法指向一个有效的内存空间,操作系统不允许操作此指针指向的内存区域

注释:野指针是不会直接引发错误的,而野指针指向的内存空间会出现问题的。 

3.1 野指针成因 

1.指针未初始化:指针变量终究只是一个变量(就和全局变量与局部变量一样),如果不给这个变量进行初始化,那么这个变量将会存放随机值

下面进行代码演示:

    int* p; //局部变量指针为初始化,默认为随机值
//正确写法为:int* p = NULL;*p = 20;

2.指针越界访问:在数组这一节中,我们学习数组越界访问,其实指针越界访问与其类似,指针指向的空间超出了其分配的合理空间

下面进行代码演示:

    int arr[10] = {0};int* p = arr;for(int i = 0; i <= 10; i++)
//正确写法为:for(int i = 0; i < 10; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++) = i;}

3.指针指向的空间释放:在未学习动态内存开辟时,我们先用函数释放来解释这个成因。建立一个返回值为指针类型的函数,在主函数中用指针变量进行接收,当程序出函数体后,原先函数所指向的空间进行释放,此时指针就为野指针

下面进行代码演示:

int* test()
{int a = 10;return &a;
}
int main()
{int* p = test();printf("%d\n", *p);return 0;
}

3.2 如何规避野指针 

  1. 指针初始化
  2. 小心指针越界
  3. 指针指向的空间释放,及时置NULL
  4. 避免放回局部变量的地址
  5. 指针使用之前检查有效性

3.2.1 指针初始化要注意两个点 

先看代码,进行举例:

int a = 10;
int* p = &a;
  • 如果明确指针应该指向哪里的话,就应该初始化正确的地址
  • 如果不能明确指针应该指向哪里的话,安全起见要将指针初始化为NULL (空指针,就是0)

3.2.2 指针使用之前要检查有效性

#include <stdio.h>
int main()
{int* p = NULL; //不管三七二十一,我们要进行初始化//……int a = 10;p = &a;if(p != NULL)*p = 20;return 0;
}

       在这里,我们要先说一句,NULL是0,其实它也是一个地址,但是在我们用户手中是无法访问的,一旦我们去访问,程序就会崩溃。 

悬空指针


四、指针运算

4.1 指针 +- 整数

int main()
{int arr[] = { 0,1,2,3,4,5,6,7,8,9 };//            0 1 2 3 4 5 6 7 8 9 //使用指针打印数组的内容int* p = arr;for (int i = 0; i < 10; i++){printf("%d ", *(p + i));//p指向的是数组首元素//p+i 是数组中下标为i的元素的地址//p+i 起始时跳过了i*sizeof(int)个字节}printf("\n");return 0;
}

 扩展:arr == p

            arr+i == p+i 

            *(arr+i) == *(p+i) == arr[i]

            *(i+arr) == i[arr]

4.2 指针 - 指针

  • 指针 - 指针的前提是:两个指针指向同一块区域,指针类型相同的
  • 指针 - 指针差值的绝对值是:指针和指针之间的元素个数
int arr[10];
printf("%d\n", &arr[0] - &arr[9]);  //-9
printf("%d\n", &arr[9] - &arr[0]);  //9

  

模拟实现一下strlen()函数

size_t my_strlen(char* ptr)
{char* s = ptr;while(*s)
//还可以这样写:while(*s != '\0')s++;return s - ptr;
}

4.3 指针的关系运算

#define N_VALUES 5
for(vp = &values[N_VALUES];vp > &values[0];)
{*--vp = 0;
}

代码简化,将这个代码进行修改:

for(vp = &values[N_VALUES];vp > &values[0]; vp--)
{*vp = 0;
}

       实际上在绝大部分的编译器上是可以顺利完成任务的,然而我们还是要避免这样写,因为标准并不能保证这个方法可行。 

标准规定: 

       在C语言中,允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。


五、指针和数组

在一小部分中,我们要知道:

  • 指针就是指针,指针变量就是变量,是用来存放地址的,指针变量的大小是4/8个字节
  • 数组就是数组,可以存放一组数,数组的大小是取决于元素的类型和个数
  • 数组的数组名是数组首元素的地址(两种情况除外),指针变量是可以访问地址的

在绝大多数情况下,数组名和数组首元素的地址是一样的,看下图:

总结:

数组名表示数组首元素的地址。 

但是有两个例外:

  1. sizeof(数组名),数组名单独放在sizeof内部,数组名表示整个数组,计算的是数组的大小,单位是字节。
  2. &数组名,数组名表示整个数组,取出的是数组的地址。数组的地址和数组首元素的地址,值是一样的,但是类型和意义是不一样的。

       既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问就成为可能,那我们可以直接通过指针来访问数组。看下下面代码:

int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,0 };int* p = arr; //指针存放数组首元素的地址int sz = sizeof(arr) / sizeof(arr[0]);for (int i = 0; i < sz; i++){printf("%d ", *(p + i));}return 0;
}

六、二级指针

       指针变量也是变量(一级指针变量),是变量就有地址,那指针变量的地址存放在哪里?这个就是二级指针。下面就是代码解释:

int a = 10;
int* p = &a; //p是指针变量,一级指针变量
int* * pp = &p; //pp是指针变量,二级指针变量
//你还可以继续写,有几个*,就是几级指针变量
//int** * ppp = &pp; //ppp是指针变量,三级指针变量


七、指针数组

       指针数组是指针还是数组呢?答案是:是数组,是存放指针的数组。我们可以使用指针数组来模拟实现一个二维数组。

int main()
{int arr1[] = { 1,2,3,4,5 };int arr2[] = { 2,3,4,5,6 };int arr3[] = { 3,4,5,6,7 };int* arr[] = { arr1, arr2, arr3 };for (int i = 0; i < 5; i++){for (int j = 0; j < 5; j++){printf("%d ", arr[i][j]);}printf("\n");}return 0;
}

  

总结

       在这一部分,小编详细地编写了有关初阶指针的一篇博客。希望大家看完以后,进行点评,谢谢大家!

相关文章:

初始C语言(7)——详细讲解有关初阶指针的内容

系列文章目录 第一章 “C“浒传——初识C语言&#xff08;1&#xff09;&#xff08;更适合初学者体质哦&#xff01;&#xff09; 第二章 初始C语言&#xff08;2&#xff09;——详细认识分支语句和循环语句以及他们的易错点 第三章 初阶C语言&#xff08;3&#xff09;——…...

ArcGIS Pro技术应用(暨基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例应用)

GIS是利用电子计算机及其外部设备&#xff0c;采集、存储、分析和描述整个或部分地球表面与空间信息系统。简单地讲&#xff0c;它是在一定的地域内&#xff0c;将地理空间信息和 一些与该地域地理信息相关的属性信息结合起来&#xff0c;达到对地理和属性信息的综合管理。GIS的…...

RISC-V公测平台发布 · 数据库在RISC-V服务器上的适配评估

前言 上一期讲到YCSB在RISC-V服务器上对MySQL进行性能测试&#xff08;RISC-V公测平台发布 使用YCSB测试SG2042上的MySQL性能&#xff09;&#xff0c;在这一期文章中&#xff0c;我们继续深入讨论RISC-V数据库的应用。本期就继续利用HS-2平台来测试数据库软件在RISC-V服务器…...

UE5.2 LyraDemo源码阅读笔记(五)输入系统

Lyra里使用了增强输入系统&#xff0c;首先知道增强输入系统里的三个类型配置。 一、Input Actions (IA)&#xff1a; 输入操作带来的变量&#xff0c;与玩家的输入组件绑定&#xff0c;回调里驱动玩家行为。 二、InputMappingContext&#xff08;IMC&#xff09;&#xff1a…...

线段树详解——影子宽度

OK&#xff0c;今天来讲一讲线段树~~ 线段树是什么线段树的实现线段树的时间复杂度线段树的应用线段树的节点结构其他操作和优化例题——影子宽度输入输出格式输入格式输出格式 输入输出样例输入样例输出样例 例题讲解 线段树是什么 线段树&#xff08; S e g m e n t Segmen…...

使用R语言绘制折线图

写在前面 昨天我们分享了使用Python绘制折线图的教程,跟着NC学作图 | 使用python绘制折线图,考虑到很多同学基本不使用Python绘图。那么,我们也使用R语言复现此图形。 此外,在前期的教程中,我们基本没有分享过折线图的教程。因此,我们在这里也制作一期关于折线图的教程。…...

无涯教程-Perl - wantarray函数

描述 如果当前正在执行的函数的context正在寻找列表值,则此函数返回true。在标量context中返回false。 语法 以下是此函数的简单语法- wantarray返回值 如果没有context,则此函数返回undef&#xff1b;如果lvalue需要标量,则该函数返回0。 例 以下是显示其基本用法的示例…...

【gitkraken】gitkraken自动更新问题

GitKraken 会自动升级&#xff01;一旦自动升级&#xff0c;你的 GitKraken 自然就不再是最后一个免费版 6.5.1 了。 在安装 GitKraken 之后&#xff0c;在你的安装目录&#xff08;C:\Users\<用户名>\AppData\Local\gitkraken&#xff09;下会有一个名为 Update.exe 的…...

《Java Web程序设计》试卷03

《Java Web程序设计》试卷03 课程编码&#xff1a; 301209 适用专业&#xff1a; 计算机应用(包括JAVA方向) 注 意 事 项 1、首先按要求在试卷标封处填写你所在的系&#xff08;部&#xff09;、专业、班级及学号和姓名&#xff1b; 2、仔细阅读各类题目的回答要求&#xff0c;…...

怎么查看小程序中的会员信息

商家通过查看会员信息&#xff0c;可以更好地了解用户&#xff0c;并为他们提供更个性化的服务和推荐。接下来&#xff0c;就将介绍如何查看会员信息。 商家在管理员后台->会员管理处&#xff0c;可以查看到会员列表。支持搜索会员的卡号、手机号和等级。还支持批量删除会员…...

网络安全—黑客—自学笔记

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…...

深度解读波卡 2.0:多核、更有韧性、以应用为中心

本文基于 Polkadot 生态研究院整理&#xff0c;有所删节 随着波卡 1.0 的正式实现&#xff0c;波卡于 6 月 28 日至 29 日在哥本哈根举办了年度最重要的会议 Polkadot Decoded 2023&#xff0c;吸引了来自全球的行业专家、开发者和爱好者&#xff0c;共同探讨和分享波卡生态的…...

微服务中间件--Eureka注册中心

Eureka注册中心 a.eureka原理分析b.搭建eureka服务c.服务注册d.服务发现 a.eureka原理分析 1.每个服务启动时&#xff0c;将自动在eureka中注册服务信息 (每个服务每隔30秒发送一次的心跳续约&#xff0c;当某个服务没有发送时&#xff0c;eurekaServer将自动剔除该服务&#x…...

积跬步至千里 || 矩阵可视化

矩阵可视化 矩阵可以很方面地展示事物两两之间的关系&#xff0c;这种关系可以通过矩阵可视化的方式进行简单监控。 定义一个通用类 from matplotlib import pyplot as plt import seaborn as sns import numpy as np import pandas as pdclass matrix_monitor():def __init…...

zookeeper详细介绍

ZooKeeper是一个开源的分布式协调服务,具有以下一些关键特点: 数据模型 ZooKeeper的数据模型采用层次化的多叉树形结构,每个节点称为znode,类似于文件系统中的文件和目录。每个znode可以存储数据和控制信息。一致性保证 ZooKeeper通过ZAB协议,实现分布式环境下数据的强一致性,…...

面板市场趋势分析:价格上涨势头或将减缓 | 百能云芯

8月末&#xff0c;面板价格报价公布&#xff0c;市场研究机构TrendForce指出&#xff0c;电视面板今年以来已经上涨超过30%&#xff0c;虽然下游品牌商对于价格上涨提出了不同声音&#xff0c;但由于面板厂商采取了按需生产的策略&#xff0c;8月仍然出现了3~5%的价格上涨。Tre…...

JVM性能调优

java 如何跨平台&#xff0c;如何一次编译到处执行 是由于java在不同的jvm上编译&#xff0c;jvm在软件层面屏蔽不同操作系统在底层硬件与指令上的区别。 jvm 包括 new 的对象都是放在堆中 栈&#xff0c;给线程单独使用&#xff08;线程私有&#xff09;&#xff0c;存储一个…...

【全链路追踪】XXL-JOB添加TraceID

文章目录 一、背景调用路径部署环境问题 二、方案三、Demo示例1、MDC2、RequestInterceptor3、HandlerInterceptor4、logback.xml 四、后续改进思路 一、背景 首先这个项目属于小型项目&#xff0c;由于人手以及时间限制&#xff0c;并未引入Skywalking等中间件来做调用链路追…...

[Unity]Lua本地时间、倒计时和正计时。

惯例&#xff0c;直接上代码&#xff1a; --正计时开始时的时间戳 self.begin_time os.time() --倒计时时长&#xff0c;01:30:00 self.countdown_time 5400 --是否开始计时 self.is_update_local_time true--Unity Update function time_transition:update_local_timer()i…...

探究HTTP API接口测试:工具、方法与自动化

本文将深入探讨HTTP API接口测试的重要性&#xff0c;并介绍了相关工具、方法以及自动化测试的实施&#xff0c;同时比较了HTTP和API接口测试的区别。从不同角度解析这一关键测试领域&#xff0c;帮助读者更好地理解和应用于实际项目中。 在如今数字化的世界中&#xff0c;软件…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

【kafka】Golang实现分布式Masscan任务调度系统

要求&#xff1a; 输出两个程序&#xff0c;一个命令行程序&#xff08;命令行参数用flag&#xff09;和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽&#xff0c;然后将消息推送到kafka里面。 服务端程序&#xff1a; 从kafka消费者接收…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...