【C语言期末不挂科——指针篇1】

C语言指针初阶

文章目录

  • C语言指针初阶
      • **什么是指针?**
          •    **1)初识指针**
          •   **2)地址的大小**
          •   **3)指针变量**
      • **指针的类型**
          •    **1)指针对整数加减运算**
          •   **2)指针的解引用**
      • **野指针**
          •   **1)为什么会有野指针**
          •   **2)如何避免野指针**
      • **指针运算**
          •   **1)指针 + - 整数**
          •   **2)指针-指针**
          •   **3)指针的关系运算**
      • **数组和指针**
      • **二级指针**
      • **指针数组**

前言:

  对于许多正在学习C语言的小伙伴来说,指针可能会让你非常的头疼,很多人不知道如何控制指针变量,甚至都不敢用指针来写代码。但是在实际的开发中还是经常会和指针打交道的,今天我们开启C语言指针系列的章节学习~
在这里插入图片描述


什么是指针?

   1)初识指针

  指针是什么?这个我们先不着急,我们先来模拟一个场景:

  [事件1] 现在,假设你今天要去西藏旅游,到了地方总得有住的地方,于是你去希望旅馆定了一个房间号为302的房间。你是第一次来这个旅馆并不熟悉房间的排列,所以你得一个一个的去找到你的房间。你按着顺序找到了302的房间,并将行李放了进去… [结束]

在这里插入图片描述

  现在就可以回答前面的问题了,指针其实就是地址,事件1的房间号就可看作地址,有了房间号,我们就可以找到对应的房间,将行李都放进房间了。指针也是如此:指针通过地址进而找到对应的内存空间从而进行访问。

  对于指针:

指针是内存中一个最小单元的编号,也就是地址。

  注意 我们平常所说的指针,其实是指 指针变量,是用来存放地址的 变量。

我们也可以这样来理解指针:在这里插入图片描述
  通过指针的地址来找到对应的内存空间。


  2)地址的大小

  我们已经了解了指针就是地址,那么地址又是什么?实际上:

  在计算机运行时,数据会存放在内存中,内存会以 字节 为单位划分为多个存储空间,并且为每个字节默认设置一个对应的编号,这个编号就是地址。

  可能你还会有疑问:“为什么内存会以字节为单位划分呢?”

  其实经过前人的计算与考量,发现一个字节给一个对应的地址是比较合适的。在32的机器上,假设有32根地址线,每根地址线在寻址的时候产生的高低电平就是0和1。

  那么32根地址线产生的地址就会是:

00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000001
00000000 00000000 00000000 00000002

111111111 111111111 111111111 111111111

  这里就会产生2^32 次方个地址。如果每个地址来标识一个字节,那么我们就能给大约4GB(2^32 Byte = = 2^32 /1024KB = = 2^32/1024/1024MB= =2^32/1024/1024/1024GB = = 4GB)的的空间进行编址了。同样的方式,64位机器能编址多大空间?可以自己算算。

  这里我们就知道了:

1、在32位机器上,地址是32个0或1组成的二进制序列,地址有 4个字节 的空间的大小来存储,所以在32位机器下,一个指针变量的大小就是4字节
2、在64位的机器上,有64个地址线,一个指针变量的大小就是8个字节了


  3)指针变量

  还记不记得我们在学C语言中用到的 ‘&’ 符号?是不是很眼熟?没错,我们经常在scanf函数里面用到这个符号,其实这个符号叫做: 取地址操作符 。顾名思义,就是用来提取变量的地址。

  我们可以通过& 来取出变量的内存地址,把地址可以存放到一个变量中,这个变量就是指针变量

#include<stdio.h>int main()
{int a = 10;//整形大小为4个字节int *p = &a;//取变量a的地址赋给指针变量p,虽然整形大小为4个字节//但是指针存储的仅仅是四个字节中的第一个起始字节return 0;
}

  总结

1、 指针变量是用来存放地址的
2、 在32位平台下,指针大小为4字节,在64位平台下,指针大小为8字节


指针的类型

  看到标题你可能会有些疑问:既然我们的指针只能保存一个字节的内容,我们为什么还要给指针分为不同的类型呢?

  实际上,我们规定指针这样定义:

int a = 0;
int *p = &a;float b = 0;
float *pb = &b;double c = 0;
doublr *pc = &c;
//...

  我们可以看到,指针变量的 定义方式为:类型 + * 而指针前面的类型表示指针的类型,我们可以看到,指针的类型有,int,double,float…我们常用的类型都有对应的指针类型。

  那这些指针类型究竟有什么用呢?代表什么意思呢?


   1)指针对整数加减运算

  我们来看这样一段代码:

#include<stdio.h>int main()
{int a = 1;char *pa1 = (char *)a;//既然指针只保存一个字节的值,那我们不妨直接把int强转成char
//只取int的首个字节的地址进行操作看看会发生什么? int *pa2 = &a;//将未强转的类型也用指针保存,用来做对照 printf("%p\n", &a);//地址打印用%p printf("%p\n", pa1); printf("%p\n", pa1 + 1);printf("%p\n", pa2);printf("%p\n", pa2 + 1);return 0;
}

  那么结果会是多少呢?

在这里插入图片描述

  我们发现第一个与第二个和第四个的打印结果是相同的,也就是说他们的起始地址是相同的,第一个和第四个就不用多说,两个是同一个变量取地址打印。

  第二个结果也刚好能验证我们指针取的地址是元素的首个字节的地址。

  可以看到,pa1 + 1的地址要比pa1的地址大了1(16进制),也就是说pa1向后加一就是往后走一个字节的距离。

  再来看pa2与pa2 + 1,这里的差值却为4(十六进制10 - 0C),也就是说pa2加一是跳过了4个字节。我们发现,他们跳过的字节数刚好和指针对应的类型大小相同!这里我们就可以得出结论

指针类型决定了指针向前或向后走一步的步长(距离)


  2)指针的解引用

  我们已经知道了指针如何在内存中工作的,那么我们该如何将指针给用起来呢?其实啊,我们有了变量的地址,保存在指针变量里,接下来就是放行李的过程,也就是对内存空间进行访问。

  [事件2] 你打开了302房间的房门,刚走进去,不禁皱起了眉头,里面的杯子还是乱的,垃圾桶还没清理,甚至地下还有垃圾,你直接去找了酒店前台,前台十分抱歉,于是叫来了保洁阿姨,很快的,你的房间就焕然一新了,上个房客剩下的东西统统清理干净,随后将你的东西放进角落…[结束]

  指针的意义就是为了来管理我们的内存,在C语言中用指针来访问内存有一个专门的运算符:*解引用运算符 ,这里的解引用,就可以对指针指向的内存空间随意访问啦。

用法为:

int a = 0;
int *p = &a;//正常取变量地址*a = 1;//这就是对指针所指向的内存空间进行访问
//也就是说,指针可以通过解引用来更改变量a的内容

  这里将原来的0通过指针解引用改变为了1,酒店里你发现订的房间居然很乱?现在是你要住进来,你可不管之前住的是谁。这就是通过对指针解引用,来访问内存,可以对于原来的值进行修改。

  注意:初学者总是会搞错指针类型的大小与指针所指向变量的大小关系,指针的 大小永远为4/8个字节。我们来看下面例子:

#include<stdio.h>int main()
{printf("%d\n",sizeof(int *));//sizeof对不同的指针类型求大小printf("%d\n",sizeof(char *));printf("%d\n",sizeof(short *));printf("%d\n",sizeof(long *));printf("%d\n",sizeof(float *));printf("%d",sizeof(double *));//... return 0;} 

  得出的结果为:

在这里插入图片描述

  其实说白了指针就是地址,指针可不管你是int、还是double还是什么类型,到我这里都是地址,指针的类型大小是跟指针所指向的类型无关,我的机器为64位机器,所以我的指针大小就一定是8个字节。


  我相信你还有一些疑问:“还是那个问题,既然指针只需要一个字节的地址,那为什么还要分什么类型,我全都是char *不就完了吗?”。

  其实上面我已经解释了为什么指针需要类型,这里在从解引用的角度来分析一下,我们来看下面的例子:

#include<stdio.h>int main()
{int a = 0x44332211;//这里不是地址,而是16进制的数字进行赋值int *p = &a;//整形指针取地址printf("%x\n",*p);//以十六进制形式打印char *pa = (char *)&a;//字符指针取地址printf("%x\n", *pa);//十六进制打印printf("%x\n", *(pa+1));//指针向下一个位置访问return 0;} 

在这里插入图片描述

  由打印结果我们可以看到:不同类型的指针使用解引用而访问到不同的字节数,这里char*指针只访问了变量a的一个字节,而int*指针访问了变量a的4个字节。

总结:

指针的类型 决定了指针解引用时候有多大权限(访问几个字节数


野指针

  1)为什么会有野指针

  哎呀,指针真好用!我有了谁的地址,我就可以随便来玩了,有一天,你写了这样一段代码:

#include<stdio.h>int main()
{int *p;*p = 20;printf("%d\n", *p);return 0;
}

  这个时候在打印:在这里插入图片描述

  哎呀,这里程序怎么挂了?其实,这里没有对指针p进行初始化,他没有保存任何变量的地址。这个指针也是一个局部变量,当局部变量不初始化的时候,内容是随机值。

  既然是随机值,也就是说这里的指针是随机的地址,你说万一这地址里面存的是什么重要数据,你在这里把他改了?是不是就太危险了?!

  这种有越界访问的指针我们统称:野指针

野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)


  除此之外,还有其他导致野指针的原因,我们来看下面代码:

#include <stdio.h>
int main()
{int arr[10] = {0};int *p = arr;//相当于int *p = &a[0];int i = 0;for(i=0; i<=11; i++){//当指针指向的范围超出数组arr的范围时,p就是野指针*(p++) = i;//先解引用赋值,再后置++使指针指向下一个位置}return 0;
}

在这里插入图片描述

  在C语言中,数组名表示数组首元素地址,我们将数组的首元素地址给了指针p,我们通过for循环用指针对数组进行访问,这里我们只有10个元素,我们却要访问12次,那么就会发生越界访问问题。

  这里也就会造成指针越界访问的问题,同样,当出了数组之后,指针也会变成随机值,造成越界访问。


  [事件3] 这几天在西藏你玩的很爽,玩够了,也该回家族打理产业了,然后你就想在过了今天晚上,明天就回去,可是当你走到302的房门前,发现你的行李整齐地摆放在地下,这个时候你才想到,原来房间今天早上就到期了…身上的钱也只够回家了,看来今天只能露宿街头了…[结束]

  除了上面的情况之外,我们还有一种常见的导致野指针的问题:

#include<stdio.h>int *Test()
{int a = 1;int *p = &a;return p;
}int main()
{int *ret = Test();*ret = 2;printf("%d\n", *ret);return 0;
}

  我们来仔细分析一下:从main函数开始,第一个语句直接进入到Test函数里,那么Test函数会在函数栈帧上开辟一块空间,变量a也开了一块空间,指针变变量p也开辟一块空间用来记录a的地址。

  在函数调用结束的时候,会创建一个临时变量记录返回值,函数栈帧销毁,变量a和指针变量p都销毁了,临时变量被返回值传到main函数的ret。

  那么ret就记录下了这个地址,我们对ret解引用赋值,但是这个时候Test函数已经销毁了,里面的变量的值已经回收了,这个时候再去访问这个已经回收的地址,那么肯定会发生越界访问的。也就是说,你的房间已经被退房了,这个时候你还想去302,就是非法的了。

  总结:

1、野指针会造成越界访问的问题,因此对于指针控制范围非常重要。
2、已经回收资源的地址,再次访问这个地址就是非法访问。


  2)如何避免野指针

  由上面的学习我们知道指针玩不好代价是很大的,那么有没有什么办法防止指针越界等问题呢?要想玩好指针,你必须要记住这五个点:

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

  指针在使用之前一定要初始化,如果没有需要引用的对象,就将指针置为NULL,如下:

#include<stdio.h>int main()
{int a = 10;int *p = &a;int *ptr = NULL;return 0;
}

  这里的NULL我们可以转到定义来看一下:

  我们可以看到,在c++中的NULL就是0,在C语言中NULL的类型就是(void *)空指针类型,严格来说C语言的NULL是更加正确的。

  牢记这5点,妈妈就再也不用担心我的指针老是出错了。


指针运算

  我们已经理解指针的基本功能了,除了上面的基本功能,指针还有一个很重要的东西———指针运算。

  1)指针 + - 整数

  我们前面已经学过,指针加上整数就是跳过整数倍指针类型个字节,就像:

#include<stdio.h>int main()
{int a = 0x44332211; char *p = (char *)&a;printf("%x\n", *p);printf("%x\n", *(p + 1));printf("%x\n", *(p + 2));printf("%x", *(p + 3));return 0;} 

在这里插入图片描述

  指针加上整数除了可以进行读取数据以外,还可以连续的存储数据,我们看下面代码:

#include<stdio.h>#define N 5//数组元素个数int main()
{int arr[N] = { 0 };int *parr = NULL;//指针用来保存数组首元素地址for(parr = &arr[0] ; parr < &arr[N] ; )//将数组首元素地址赋值、小于判断条件就一直执行{*parr++ = 1;//指针解引用对内存空间进行赋值,随后+1指向下一个位置}int i = 0;for(i = 0 ; i < N ; i++)//打印出来数组里的值看看是否改变{printf("%d ", arr[i]);}return 0;
}

在这里插入图片描述

  我们用指针解引用访问对应的内存空间从而完成了赋值操作。这种是指针parr的位置一直在变化,如果不想要指针的位置,我们可以这样写:

#include<stdio.h>#define N 5int main()
{int arr[N];int *parr = &arr[0];int sz = sizeof(arr) / sizeof(arr[0]);//sizeof(数组名)求出整个数组的字节大小
//然后再除上一个元素的大小,就是数组元素的个数。sizeof(arr) == Nint i = 0;for(i = 0 ; i < sz ; i++){*(parr + i) = 1;}for(i = 0 ; i < N ; i++){printf("%d ", arr[i]);}return 0;
}

在这里插入图片描述

  这样就能控制指针的地址不变,而完成数组元素的赋值了。

  总结:

  指针加减整数的意义就是指针跳过了 指针类型大小*整数 个字节,进而访问对应的内存空间。


  2)指针-指针

  我们来看下面的代码:

#include<stdio.h>int main()
{int arr[10] = { 0 };printf("%d\n", &arr[9] - &arr[0]);return 0;
}

  这里两个指针相减,你来思考一下,得出的结果是多少?相信聪明的你能很快的得出正确的答案。我们直接来看结果:

在这里插入图片描述

  答案是9,不知道你想对了没有,我们取了数组元素的第10个元素地址,与第一个元素地址作差,得出来的结果是9,正好就是两个数组元素的距离。

  但是如果是这两种情况:

#include<stdio.h>int main()
{int arr[10];double a = 1;int *ptr1 = &arr[0];double *ptr2 = &a;printf("%d", ptr1 - ptr2);
}

在这里插入图片描述

  如果采用了不用类型的参数进行相减,就会报错,而且最好是像数组这种连续的内存空间使用指针相减,否则相减出来的值是几乎没有什么意义的。

  总结:

  1、指针-指针得到的就是指针和指针之间元素的个数。
  2、两个指针相减的前提是他们的类型必须相同。
  3、指针相减的到时元素的个数,所以在连续的内存空间下相减是比较有意义的,不推荐两个毫不相关的指针相减,因为几乎没什么意义。


  3)指针的关系运算

  我们的地址是有大小的,有高低地址之分,而指针的关系运算就是比较指针的大小。我们来看下面的代码:

#include<stdio.h>#define N 5int main()
{int arr[N] = { 1 };int *parr = NULL;for(parr = &arr[5] ; parr > &arr[0] ; ){*--parr = 0;}int i = 0;for(i = 0 ; i < N ; i++){printf("%d ", arr[i]);}return 0;
}

  数组一共有5个元素,将数组元素全部初始化为1,随后我们将数组的最后一个元素的地址放进指针变量parr里面,我们准备使数组中的元素从后往前进行赋值,将数组中的元素全部赋值为0。

  详细的工作原理如下:
在这里插入图片描述
  当然你的for循环里也可以这样写:

for(parr = &arr[5] ; parr >= &arr[0] ; parr--)//这两种方式都是相同的
{*parr = 0;
}

  得到的结果同样是:

在这里插入图片描述

  指针的比较还有一个要点:就是只能向后比较,但是不能向前比较,如下图:

在这里插入图片描述

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


数组和指针

  指针和数组是什么关系呢?我们前面也使用了数组名作为首元素地址,那么数组与指针究竟有着什么样的渊源呢?大型纪录片之《指针与数组的故事》持续为您播出…

  指针变量就是指针变量,不是数组指针变量的大小为4/8个字节,专门用来存放地址的。数组也就是数组,不是指针,数组有一块连续的内存空间,可以存放1个或多个类型相同的数据

  我们来看下面的代码:

#include<stdio.h>int main()
{int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };int len = sizeof(arr)/sizeof(arr[0]);int *p = arr;//指向数组首元素地址int i = 0;for(i = 0 ; i < len ; i++){printf("%p == %p\n",p + i, &arr[i]);}return 0;
}

在这里插入图片描述
  我们可以看到,数组与指针的地址全部都是对应的,一模一样,所以说,数组名就是首元素地址,那么以后你就可以不使用[]来访问数组的内容了,可以使用指针 + 偏移量 的方式来访问数组元素:

int a[1000];
int *p = arr;
for(int i = 0 ; i < sizeof(arr)/sizeof(arr[0]) ; i++)
{*(p + i) = 1;//i就为偏移量
}

  数组与指针的联系

  前面我们也用到了,数组名就是首元素地址,数组名 == 地址 == 指针 ,当我们知道数组首元素的地址的时候,又因为数组是连续存放的,所以通过指针就可以遍历访问数组,前面也演示过了,数组可以通过指针来访问

  数组名就是数组的首元素地址,但是在这两个情况下是例外的

//sizeof(数组名)  sizeof数组名是直接得到整个数组的字节大小
//& 数组名		&数组名 如果进行+1操作是直接跳过一整个数组

  其余的情况数组名就是首元素地址。


二级指针

  指针的基本用法我们大概了解了,但是我们了解的是 “一级指针” 的用法,其实还存在着二级指针、三级指针…多级指针,因为二级指针用的最多,所以我们在这里主要阐述二级指针,其他指针的情况类比就行了。

  那么究竟什么是二级指针呢?我们先来看我们日常所说的一级指针:

int a = 0;
int *pa = &a;//这里的指针pa就是一级指针

  我们再来看看二级指针:

int a = 0;
int *pa = &a;//这里的指针pa就是一级指针int **ppa = &pa;//这里为二级指针

  我们要理解一个东西,指针变量也是变量 啊,既然是变量,那么就一定有内存空间来存储指针变量,而二级指针就是取一级指针变量的地址 的指针。如下图:

在这里插入图片描述

  这里二级指针的两个*可以这么来理解:int **是种类型,而我们可以把int ** 看成int* * 前面的int*是指向变量的类型,也就是一级指针(一级指针的类型为int *),而你本身是二级指针,指针的类型必须是int *,加上一级指针的类型int* 就是int ** 。

  同样,三级整形指针的返回类型就为int ***,多级指针以此类推…我们来看下面代码:

int a = 0;
int *p = &a;//一级指针
int **pp = &p;//二级指针

  现在我们想通过二级指针来修改变量a的值,我们该如何做?我们是如何由一级指针访问变量内存的?使用解引用来访问:

*p = 1;//以上面代码为续接

  那我们二级指针解引用就找到了一级指针的地址,然后我们在解引用一次,不就可以访问变量a了吗?

* *pp = 100;//两次解引用,第一次解引用找一级指针内存,第二次解引用就访问到变量a了

  以上就是二级指针的具体用法了,多级指针以此类推。


指针数组

  在我们C语言中存在着这样一个东西————指针数组 ,那么请你思考一下,指针数组究竟是指针呢还是数组呢?

  答:是一个数组,用来存放指针的数组。

  我们知道,数组有不同的类型,有int型数组,double型数组、char型数组…

在这里插入图片描述
  那么我们的指针数组呢?刚才我们也回答了,指针数组里面存放的都是指针变量,那这里的数组名其实就是二级指针了。

在这里插入图片描述

  我们来看下面代码:

#include<stdio.h>int main()
{char arr1[] = "abcdef";char arr2[] = "talk is cheap";char arr3[] = "show me code";char *parr[] = { arr1, arr2, arr3 };char **p = parr;return 0;} 

  我们可以通过指针p来访问数组中的元素的指向。
在这里插入图片描述
  字符指针数组的每个值的类型都是char*,而数组名就为数组的首元素地址,首元素为指针,所以数组名就是二级指针。

 ; 这里我们用二维数组的方式打印出各个数组里的字符串,我们只需要:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main()
{char arr1[] = "abcdef       ";char arr2[] = "talk is cheap";char arr3[] = "show me code ";char *parr[] = { arr1, arr2, arr3 };char **p = parr;int len = strlen(arr1);int i = 0;for(i = 0 ; i < 3 ; i++){int j = 0;for(j = 0 ; j < len ; j++){printf("%c",parr[i][j]);//通过[]来访问下标}printf("\n");}return 0;} 

在这里插入图片描述

  我们可以看到,完全可以用二级指针来模拟二维数组。其实在第二层的for循环里面我们可以这样改:

for(j = 0 ; j < len ; j++)
{printf("%c",*(parr[i] + j));
}
printf("\n");

  先由数组名可以访问每个元素,而每个元素的类型都是char*所以我们可以使用偏移量来对每个指针变量所指向的数组进行访问。当然,这里还有其他的写法可以支持访问,大家可以自由的探索。


  感谢你能看到这,这期就到这里啦,如果还想看后续内容就给博主点点关注!C语言指针篇正在持续更新~~在这里插入图片描述

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

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

相关文章

【科技素养】蓝桥杯STEMA 科技素养组模拟练习试卷F

1、常见的加密算法可以分为对称加密算法和非对称加密算法&#xff0c;以下关于它们的描述正确的是 A、AES是一种常见的非对称加密算法 B、凯撒密码是一种非对称加密 C、非对称加密算法的解密使用的秘钥与加密不同 D、对称加密算法无法被暴力破解 答案&#xff1a;C 2、12根…

【LeetCode:2736. 最大和查询 | 贪心 + 二分 + 单调栈】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

SpringBoot--中间件技术-4:整合Shiro,Shiro基于会话SessionManager实现分布式认证,附案例含源代码!

SpringBoot整合安全中间件Shiro 技术栈&#xff1a;SpringBootShiro 代码实现 pom文件加坐标 Springboot版本选择2.7.14 &#xff1b;java版本1.8 &#xff1b; shiro做了版本锁定 1.3.2 <properties><java.version>1.8</java.version><!--shiro版本锁定…

一起学docker系列之四docker的常用命令--系统操作docker命令及镜像命令

目录 前言1 操作 Docker 的命令1.1 启动 Docker1.2 停止 Docker1.3 重启 Docker1.4 查看 Docker 状态1.5 查看 Docker 所有命令的信息1.6 查看某个命令的帮助信息 2 操作镜像的命令2.1 查看所有镜像2.2 搜索某个镜像2.3 下载某个镜像2.4 查看镜像所占空间2.5 删除镜像2.6 强制删…

nodejs+vue杰和牧场管理系统的设计与实现-微信小程序-安卓-python-PHP-计算机毕业设计

系统涉及的对象是奶牛。 系统使用员工有管理员和普通员工。 管理员有修改的权限&#xff0c;普通员工没有。系统包含新闻功能&#xff0c;最好是有个后台管理&#xff0c;在后台输入新闻标题和内容&#xff0c;插入图片&#xff0c;在网页上就可以展示。最好再有个轮播图。 新闻…

SpringCloud Alibaba组件入门全方面汇总(中):服务熔断降级-Sentinel

文章目录 Sentinel常见的容错思路Sentinel流量控制规则sentinel 自定义异常 sentinelresources 注解使用Feign整合Sentinel**面试题&#xff1a;结合Feign后&#xff0c;你在项目中的降级方法中会实现什么样的操作/功能&#xff1f;** Sentinel Sentinel是阿里巴巴开源的分布…

The import xxx.xxx.xxxx is never used

CTRL SHIFT O 就完成了&#xff0c;懒人&#xff0c;代码没洁癖啊&#xff0c;几千上万的代码没用的。

C++语言的由来与发展历程

C语言的由来与发展历程可以追溯到1978年&#xff0c;当时美国电话电报公司&#xff08;AT&T&#xff09;的贝尔实验室发明了C语言&#xff0c;以满足UNIX操作系统的开发需求。在C语言的基础上&#xff0c;Bjarne Stroustrup于1983年创立了C编程语言&#xff0c;作为C语言的…

鸿蒙开发|鸿蒙系统项目开发前的准备工作

文章目录 鸿蒙项目开发的基本流程介绍鸿蒙项目开发和其他项目有什么不同成为华为开发者-注册和实名认证1.登录官方网站 鸿蒙项目开发的基本流程介绍 直接上图&#xff0c;简单易懂&#xff01; 整个项目的开发通过4个模块进行&#xff1a;开发准备、开发应用、运行调试测试和发…

酷柚易汛ERP - 通用设置操作指南

1、系统设置 对系统进行初步设置&#xff0c;如系统LOGO、站点名称、备案号、版权信息、尾部信息及系统相关的一些基础设置 2、应用/小程序配置 对系统移动端进行相关配置 3、短信配置 对系统短信进行配置&#xff0c;此配置用于移动端一些通知类信息发送【目前仅支持阿里云…

OpenCV快速入门:初探

文章目录 一、什么是OpenCV二、安装OpenCV三、图像读取与显示读取图像显示图像等待按键与关闭窗口 四、视频加载与摄像头调用从视频文件中读取从摄像头中读取关闭窗口与释放资源 五、图像的基本存储方式RGB矩阵矩阵操作与像素访问使用矩阵来显示图像 六、图像保存读取图像保存图…

Win10专业版如何重装-Win10专业版重装系统教程

Win10专业版如何重装&#xff1f;Win10专业版系统能够用户带来丰富的功能服务&#xff0c;用户操作需求轻松得到满足。如果我们在Win10专业版电脑中&#xff0c;遇到了系统问题&#xff0c;这时候可以考虑重新安装Win10专业版系统&#xff0c;从而解决系统出现的问题。下面小编…

gpt-4-vision-preview 识图

这些图片都是流行动画角色的插图。 第一张图片中的角色是一块穿着棕色方形裤子、红领带和白色衬衫的海绵&#xff0c;它站立着并露出开心的笑容。该角色在一个蓝色的背景前&#xff0c;显得非常兴奋和活泼。 第二张图片展示的是一只灰色的小老鼠&#xff0c;表情开心&#xf…

【0235】修改私有内存(private memory)中的MyBEEntry时,st_changecount值前后变化

上一篇: 【0234】PgBackendStatus 记录当前postgres进程的活动状态 1. pg_stat_activity中xxx实时信息如何实现? 客户端(eg:psql)在连接上postmaster之后,postmaster守护进程会fork()一个后端进场(backend process),之后此客户端的所有操作、交互均有此对应的Backen…

WPF 使用.ttf文件中的图标失败

本章讲述问题&#xff1a;WPF 使用.ttf文件中的图标失败&#xff0c;变成白框问题。 在WPF开发过程中&#xff0c;我们需要使用.ttf文件中的图标和文字&#xff0c;但是经常会遇到类似问题&#xff1a;WPF 在XMAL里增加图标字体时没办法实时显示出来只显示一个小方框&#xff0…

公寓水电管理系统

springbootmybatisthymeleaf 这次练习是尝试将layer与系统结合起来&#xff0c;将新增、修改、删除都和弹窗结合起来。 一、需求分析 二、数据库 三、模块 1、登录页面 哈哈哈&#xff0c;之前做的登录页面都好丑&#xff0c;这是目前做的最好看的一次了。 超级管理员&…

JS-项目实战-鼠标悬浮变手势(鼠标放单价上生效)

1、鼠标悬浮和离开事件.js //当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取 Element:元素 By:通过...方式//getElementById()根据id值获取某元素let fruitTbl document.getElementById("fruit_tbl");//table.rows:获取这个表格…

20231117在ubuntu20.04下使用ZIP命令压缩文件夹

20231117在ubuntu20.04下使用ZIP命令压缩文件夹 2023/11/17 17:01 百度搜索&#xff1a;Ubuntu zip 压缩 https://blog.51cto.com/u_64214/7641253 Ubuntu压缩文件夹zip命令 原创 chenglei1208 2023-09-28 17:21:58博主文章分类&#xff1a;LINUX 小工具 文章标签命令行压缩包U…

总结 CNN 模型:将焦点转移到基于注意力的架构

一、说明 在计算机视觉时代&#xff0c;卷积神经网络&#xff08;CNN&#xff09;几十年来一直是主导范式。直到 2021 年 Vision Transformers (ViTs) 出现&#xff0c;这个领域才开始发生变化。现在&#xff0c;是时候采用受 Transformer 架构启发的基于注意力的模型了&#x…

GZ038 物联网应用开发赛题第8套

2023年全国职业院校技能大赛 高职组 物联网应用开发 任 务 书 &#xff08;第8套卷&#xff09; 工位号&#xff1a;______________ 第一部分 竞赛须知 一、竞赛要求 1、正确使用工具&#xff0c;操作安全规范&#xff1b; 2、竞赛过程中如有异议&#xff0c;可向现场考评…