C语言----指针

基本知识点:指针的定义、指针运算符和指针运算等基本概念。
重           点:字符指针、指针数组和多级指针。
难           点:利用指针类型解决复杂的应用问题。

 指针的概念

要点归纳

1.指针变量

        在计算机中,所有数据都通过变量存放在内存中,每个变量都有存储地址,对于语句int n;定义的变量n,其地址为&n,其中可以存放整数,如 2、5、8等,如图5.1(a)所示。指针就是地址(当一个数据占用多个内存单元时,该地址默认指的是首地址),它也是一种数据,可以定义专门存放变量地址的变量,如图5.1(b)所示,整型变量a、b、c可以将它们的地址存放到变量p中,这个存放变量地址的变量称为指针变量。实际上,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。

        既然指针变量的值是一个地址,那么这个地址不仅可以是变量的地址,也可以是其他数据的地址。在一个指针变量中存放一个数组或一个函数的首地址有何意义呢?因为数组或函数都是连续存放的。通过访问指针变量取得了数组或函数的首地址,也就找到了该数组或函数。这样一来,凡是出现数组、函数的地方都可以用一个指针变量来表示,只要该指针变量中赋予数组或函数的首地址即可。这样做,将会使程序的概念十分清楚,程序本身也变得精炼、高效。

        在C语言中提供两种指针运算符:

* :取指针目标运算符

& :取地址运算符

        其中,“*”表示的运算是访问地址的目标。“&”表示的运算是提取一个变量的存储区域的地址。 

        例如,在定义int x,*px之后,以下赋值语句均成立:

px = &x                                                /* 将x的地址赋给 px */
x = *px                                                /* 将px所指的值赋给x */
px = &(*px)                                        /* 将px所指值的地址赋给 px,等价于 px=px */
x = *(&x)                                            /* 将x的地址的值赋给x,等价于x=x */

提示:

        指针变量中存放的是地址值,无论何种数据的指针变量,占用的内存大小是相同的,例如char *p1;double*p2;,其sizeof(p1)和sizeof(p2)均为4(在32位操作系统中),即p1和p2 两个指针变量均占用4个字节。在任何时刻,一个指针变量只能存放一个地址值,即只能指向一个数据。 

2. 指针的定义和初始

        由于指针是一个变量,所以具有和普通变量一样的属性,在使用之前也需要定义,在指针定义的同时也可以进行初始化。

        指针定义的一般形式如下:

数据类型 *指针名

        其中,指针名前的 “*” 号仅是一个符号,表示其后的名称是一个指针变量名。这里的 “*” 号并没有访问指针目标的含义。
        与普通变量不同,指针定义时指定的数据类型并不是指针变量本身具有的数据类型而是其目标的数据类型。无论目标数据类型如何,所有指针都是具有相同格式的地址量,由于机器硬件不同,地址量的数据长度也不同。

        指针初始化的一般形式如下: 

数据类型 *指针名 = 初始地址值;

        指针初始化的过程是,系统按照给出的数据类型,在一定的存储区域为该指针分配存储空间,同时把初始值置入指针的存储空间内,从而该指针就指向了初始地址值所给定的内存空间。例如:

double x;

double *px = &x;

         把变量x的地址作为初值赋给 double 型指针 px,从而px指向了变量x的存储空间。

3. 指针运算

        指针运算是以指针变量所持有的地址值为运算量进行的运算,所以指针运算实际上是地址的计算。C语言提供的这种地址计算方法,适合于指针、数组等类型的数据。

  • 指针与整数的加减运算

        C语言的地址计算规则规定,一个地址量加上或减去一个整数n,其计算结果仍然是一个地址量,它是以运算数的地址量为基点的前方或后方第n个数据的地址。因此,指针作为地址量加上或减去一个整数n,并不是用它的地址量直接与整数n进行加法或减法运算。其运算结果应该是指针当前指向位置的前方或后方第n个数据的地址。由于指针可以指向不同数据类型,即数据长度不同的数据,所以这种运算的结果取决于指针指向的数据的类型,即目标类型(或基类型)。
对于目标类型为type的指针p,p+n(或p-n)表示的实际位置的地址值是:

p+n(或p-n)*sizeof(type)

  •  指针加1、减1运算

        指针加1、减1运算也是地址运算,是指针本身地址值的变化。指针++运算后就指向下个数据的位置,指针--运算后就指向上一个数据的位置。运算后指针地址值的变化量取决于它指向的数据类型。

  • 指针的相减

        在C语言中,两个地址量相减,并非它们的两个地址值之间直接做减法运算,两个指针相减的结果值是整数,该值表示这两个指针所指地址之间的数据个数。

  • 指针的关系运算

        目标类型相同的两个指针之间的关系运算表示它们指向的地址位置之间的关系。假设数据在内存中的存储顺序是由前向后,那么指向后方的指针大于指向前方的指针。指向不同数据类型的指针之间的关系运算是没有意义的。指针与一般整数常量或变量之间的关系运算也是无意义的。但是指针可以和零(指针零用NULL表示)之间进行等于或不等于的关系运算,即p==NULL或p!=NULL,以判定指针p是否为一空指针。

指针和数组

要点归纳

1. 指针和一维数组

        在C语言中,指针与数组之间的关系十分密切,它们都可以处理内存中连续存放的一系列数据。数组与指针在访问内存时采用统一的地址计算方法。在进行数据处理时,指针和数组的表示形式具有相同的意义。
        在C语言中规定数组名代表数组的首元素的首地址,也就是说,数组名具有地址的概念。因此,可以将数组名(即在内存中存放该数组的首地址)赋给指针。例如:

int a[10] ,*p;

p = &a[0];

p = a;

        两个语句是等价的,其作用都是把a数组的首元素的首地址赋给指针变量p。之后p+i就是数组元素a[i]的地址。访问数组元素的一般形式是:

数组名[下标] 

进一步得到访问数据运算的一般形式为:

地址量[整数n] 

        可以看出,它是一个二目变址运算,要求两个运算量。其中“口”左边的运算量必须是地址量,它可以是地址常量或地址变量。“口”内的运算量必须是整数。该运算表达式的意义是,访问以地址量为起点的第n个数据。例如,表达式a[i]的运算结果是,以地址a为起点的i号元素如果a是某个数组名,则a[i]恰好是该数组的i号元素。由此可知,C语言中数组元素的表示形式实质上是访问数据运算表达式,通过表达式的运算结果达到访问数组元素的目的。

        访问数据表达式a[i]的运算过程是,首先计算a+i得到i号元素的地址,然后访问该地址中的数据。其中a+i是按照C语言的地址计算规则进行的。由上述a[i]的运算过程看到,它与表达式*(a+i)的运算完全相同。因此在程序中a[i]和*(a+i)是完全等价的。

        在程序中,使用指针处理内存中连续存储的数据时,可以使用以下形式:

*(指针变量+i) 

        例如,对于*(p+i),根据上述等价原理,它可以写为p[i]的形式。注意不要把它误解为存在一个数组p,并访问p的i号元素。应该把它看做是一个访问数据运算表达式,它是访问以地址p为起点的i号元素。

        由于数组名是地址常量,不能对它进行任何运算。而指针可以进行一系列的运算,所以,采用指针对数组元素进行运算更方便灵活。

        归纳起来,在定义了int a[10],*p=a;的情况下: 

  • p+i或 a+i就是 a[i]的地址。地址值都要进行 a+i*d(d为a中元素对应的数据类型的字长)的运算。
  • *(p+i)或*(a+i)就是 p+i或 a+i所指向的数组元素 a[i]。数组元素中的“[]”是变址运算符,相当于*(+),a[i]相当于*(a+i)。
  • 指向数组元素的指针变量也可带下标,如p[i]与*(p+i)等价。所以,a[i]、*(a+i)、p[i]、     *(p+i)四种表示法全部等价。
  • 注意p与a的差别。p是变量,a是符号常量,不能给a赋值,语句a=p;和a++;都是错误的。

注意:

        对于定义的一维数组,如int a[10];,它含有10个整数,数组名a代表的是该数组首元素的首地址,而不是数组a的首地址,&a才是整个数组的首地址,a与&a[0]的含义相同。如“a==&a[0]”返回真,是正确的比较,而“&a==&a[0]”是错误的比较,尽管&a和&a[0]的地址值相同,但两者的含义不同。

        例如,有一下程序:

#include <stdio.h>
int main(int argc, char const *argv[])
{int a[] = {1, 2, 3}, *p = a;int i;for (i = 0; i < 3; i++){printf("%d ", *(a + i));    //通过*(a+i)操作}putchar(10);for (i = 0; i < 3; i++){printf("%d ", a[i]);       //通过a[i]操作}putchar(10);for (i = 0; i < 3; i++){printf("%d ", *(p + i));    //通过*(p+i)操作}putchar(10);for (i = 0; i < 3; i++){printf("%d ", p[i]);        //通过p[i]操作}putchar(10);return 0;
}

        上述程序每次for循环输出的结果都是123,说明*(a+i)、a[i]、*(p+i)和p[i]是等价的。另外,几种指针混合运算方式如下:

  • *p++,由于++和*同优先级,结合方向为自右向左,而这里++为后缀++,因此它等价于*p(返回其值),p++。
  • *++p而这里++为前缀++,它等价于++p,*p(返回其值)。
  • (*p)++,由于括号优先,它等价于*p(返回其值),然后将*p的结果加1。

        例如,以下程序的输出结果见其中的注释:

#include <stdio.h>
int main(int argc, char const *argv[])
{int a[] = {10, 20, 30}, *p = a;printf("%d,", *p);   /*输出:10*/printf("%d,", *p++); /*输出:10*/printf("%d,", *p);   /*输出:20*/p = a;printf("%d,", *p);   /*输出:10*/printf("%d,", *++p); /*输出:20*/printf("%d,", *p);   /*输出:20*/p = a;printf("%d,", (*p)++); /*输出:10*/printf("%d\n", *p);    /*输出:11*/return 0;
}

2. 字符指针和字符串

        字符指针指的是指向char型数据的指针。显然,字符指针也是一个指针变量。字符指针变量和字符数组有如下区别。 

        ①字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串的首地址),决不是将字符串放在字符指针变量中。

        ②)赋值方式。对字符数组只能对各个元素赋值,但不能直接给字符数组进行整体赋值(可使用strcpy()函数),例如,一下赋值是错误的:

char str[10];

str = "Hello world";

         ③ 在定义一个数组时,在编译时就已分配内存单元,有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个地址值,也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋一个地址值,则它并未具体指向哪个字符数据。

        C语言编译系统提供了动态分配和释放存储单元的函数。

  • malloc(size):在内存的动态存储区中分配一个长度为 size 的连续空间,此函数的返回值是一个指向分配域起始地址的指针,如果此函数未能成功地执行,则返回值为0。
  • calloc(n,size):在内存的动态存储区中分配n个长度为size 的连续空间,此函数的返回值是一个指向分配域起始地址的指针,如果此函数未能成功地执行,则返回值为 0。
  • free(ptr):释放由 ptr 指向的内存区,ptr 是最近一次调用 calloc或 malloc 函数时返回的值。

上面三个函数中,参数n和size 均为整型,ptr 为字符型指针。

 3. 指针和二维数组

        以二维数组为例,设二维数组a有3行5列,定义如下:

int a[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};

        其中,a是数组名,它的各元素是按行顺序存储的。a数组有3行,将它们看成3个一维数组元素,即a={a[0],a[1],a[2]},每个一维数组元素又含5个元素。这种降维的思路可以扩展到三维或三维以上的数组。

提示:

        数组名a代表的是该二维数组首元素的首地址,而不是数组a的首地址,&a才是整个数组的首地址,即a与&a[0]含义相同。如“a==&a[0]”返回真,是正确的比较,而“a==&a[0][0]”是错误的比较,也就是说,a并不是a[0][0]元素地址,同时,“&a==&a[0]”也是错误的比较。尽管a、&a、&a[0]和&a[0][0]的地址值相同,但它们各有自己的含义。归根到底,可将二维数组看成是其元素为一维数组的一维数组,a代表其首一维数组元素的首地址。 

        如图 5.2所示,由于数组名a是首元素a[0]的首地址,也就是说,a指向元素a[0],所以a+1 和a+2 分别为a[1]和a[2]元素的指针。
        a[0]是二维数组a的首元素,它又是由{a[0][0],a[0][1],a[0][2],a[0][3],a[0][4]}元素构成的,a[0]代表该一维数组的首元素的首地址,即a[0]指向首元素a[0][0],因此有“a[0]==&a[0][0]成立。a[0]+1和a[0]+2分别为a[0][1]和a[0][2]元素的指针,依次类推。 

        数组元素中的“[ ]”是变址运算符,相当于*(+),对于一维数组b,b[i]相当于*(b+j)。对二维数组元素a[i][j],将分数组名a[i]当作b代入*(b+j)得到*(a[i]+j),再将其中的a[i]换成*(a+i)又得到*(*(a+i)+j)。a[i][j]、*(a[i]+j)、*(*(a+i)+j)三者相同,都表示第i行j列元素。根据以上分析,对于图5.2所示的二维数组,可得到表5.1。

4. 数组指针

        因为数组名是常量,不能像变量那样操作,为此可以设计指向数组的指针变量,以便于数组的操作。

  • 一位数组指针

        一维数组的内存空间是连续的且大小在定义时已指定,所以可以定义一个同类型的指针对其元素进行操作。

        例如,以下程序定义一个数组a和指针pa,通过数组名a和指针pa操作输出所有元素:

#include <stdio.h>
int main(int argc, char const *argv[])
{int i;// pa作为一维数组a的指针int a[5] = {1, 2, 3, 4, 5}, *pa = a;/*①:通过a[i]方式输出所有元素------*/for (i = 0; i < 5; i++)printf("%d ", a[i]);printf("\n"); // 输出结果:1 2 3 4 5/*②:通过*(a+i)方式输出所有元素----*/for (i = 0; i < 5; i++)printf("%d ", *(a + i));printf("\n"); // 输出结果:1 2 3 4 5/*③:通过*(pa+i)方式输出所有元素---*/for (i = 0; i < 5; i++)printf("%d ", *(pa + i));printf("\n"); // 输出结果:1 2 3 4 5/*4:通过*pa方式输出所有元素------*/for (i = 0; i < 5; i++)printf("%d ", *pa++);printf("\n"); // 输出结果:1 2 3 4 5return 0;
}

         上述程序中的4种输出方式的结果相同,只是第④种方式中,当输出完毕后pa指向a[4]元素的后一个位置。

  • 二维数组指针

        二维数组可以看成是一维数组作为元素的一维数组,对每个一维数组元素可以采用前面介绍的一维数组指针的方式进行操作。

        例如,以下程序定义了一个二维数组a,a[1]是它的1号元素,也是一个一维数组,通过指针p输出a[1]的所有元素:

#include <stdio.h>
int main(int argc, char const *argv[])
{int i;int a[3][2] = {{0, 1}, {2, 3}, {4, 5}};int *p = a[1];for (i = 0; i < 2; i++)printf("%d ", *p++);printf("\n"); // 输出2 3return 0;
}

        上述程序的思路是对a的每个一维数组元素分别操作,其中p指针是一维数组指针,C语言提供了二维数组指针的概念。二维数组指针变量的一般的定义格式如下:

基类型  (*指针变量)  [整型表达式]

         其中,“整型表达式”指出二维数组中的列大小,即对应数组定义中的“下标表达式2,例如,有如下定义:

int a[2][3], (*pa)[3] = a; 

        在(*pa)[3]中,由于存在一对圆括号,所以“*”首先与pa结合,表示pa是一个指针变量,然后再与“[]”结合,表示指针变量pa的基类型是一个包含有3个int元素的数组,也就是说,pa为一个二维数组的指针变量,该数组中每列有3个元素。

        一旦定义了二维数组的指针变量,该数组指针变量可以像数组名一样使用,且可以在数组元素中移动。在前面定义二维数组指针变量pa并初始化后,有:

  • pa[i]:引用 a[i]元素。
  • pa++:让pa指向数组a的后一个一维数组元素。
  • pa--:让 pa指向数组a的前一个一维数组元素。
  • pa+1 等价于 a+1。

        当pa指向a数组的开头时,可以通过以下形式来引用 a[i][j]:

  • *(pa[i]+j)对应于*(a[i]+j)
  • *(*(pa+i)+j)对应于*(*(a+i)+j)
  • (*(pa+i))[j]对应于(*(a+i))[j]
  • pa[i][j]对应于 a[i][j] 

提示:

        数组指针pa与对应的二维数组a的差别是:二维数组a是一个常量,而数组指针pa是一个变量。 

        例如,以下程序定义一个二维数组a和该数组的指针pa,通过数组名a和指针pa操作输出所有元素:

#include <stdio.h>
int main(int argc, char const *argv[])
{int i, j;// pa作为一维数组a的指针int a[2][3] = {{1, 2, 3}, {4, 5, 6}}, (*pa)[3] = a;/*①:通过a[i][j]方式输出所有元素------*/for (i = 0; i < 2; i++)for (j = 0; j < 3; j++)printf("%d ", a[i][j]);printf("\n"); // 输出结果:1 2 3 4 5 6/*②:通过*(*(a+i)+j)方式输出所有元素----*/for (i = 0; i < 2; i++)for (j = 0; j < 3; j++)printf("%d ", *(*(a + i) + j));printf("\n"); // 输出结果:1 2 3 4 5 6/*③:通过*pa[i]+j方式输出所有元素---*/for (i = 0; i < 2; i++)for (j = 0; j < 3; j++)printf("%d ", *(pa[i] + j));printf("\n"); // 输出结果:1 2 3 4 5 6/*4:通过*(*(pa+i)+j)方式输出所有元素------*/for (i = 0; i < 2; i++)for (j = 0; j < 3; j++)printf("%d ", *(*(pa + i) + j));printf("\n"); // 输出结果:1 2 3 4 5 6return 0;
}
  •  三维数组指针

        三维数组指针变量的一般的定义格式如下:

基类型 ((*指针变量)[整型表达式1])[整型表达式2]

        其中,“整型表达式1”对应数组定义中的“下标表达式2’“整型表达式2”对应数组定义中的“下标表达式3”。例如,有如下定义:

int a[2][3][2]={1,2,3,4,5,6,7,8,9,10,11,12},((*pa)[3])[2]=a;

         pa即为三维数组a的指针变量。其定义是分两步考虑的,先定义二维数组a[2][3]的指针变量,为(*pa)[3],再定义三维数组a的指针变量为((*pa)[3])[2]。

        三位数组指针的使用与二维数组指针类似。

5. 指针和数组的对比

        指针和数组的对比如表 5.2 所示。

指针数组和多级指针

要点归纳

1. 指针数组

        当一系列有次序的指针变量集合成数组时,就形成了指针数组。指针数组是指针的集合,它的每个元素都是一个指针变量,并且指向相同的数据类型。指针数组的定义形式如下:

数据类型 *指针数组名[元素个数];

        和一般的数组一样,系统在处理指针数组定义时,也为它在一定的内存区域中分配连续的存储空间,这时指针数组名就表示该指针数组的存储首地址。例如:

int *p[3];

        由于“[]”比“*”优先级高,因此p先与[3]结合,形成p[3]的数组形式,它有3个元素。然后再与p前面的“*”结合,表示是指针类型的数组,该数组的每个元素都是整数的指针,所以每个元素都具有指针的特性。

2. 多级指针

        在C语言中,除了允许指针指向普通数据之外,还允许指针指向另外的指针,这种指向指针的指针称为多级指针。其定义形式如下: 

int *p,**pp,***ppp;

        其中,p为一级指针,pp为二级指针,ppp为三级指针。

        一般地,p用于指向普通的整数,或整型数组的元素;当指向整型数组的元素时,p++表示指向该数组的下一个元素;
        pp用于指向一个指针,p为整数的指针。大多数情况下,pp作为一个指针数组的指针,这时,pp++表示指向该指针数组的下一个元素;
        ppp用于指向一个二级指针的指针。大多数情况下,ppp作为一个二维数组指针的指针。 

 温馨提示:

        对于指针有大量练习题,如有需要,请留言……

        希望能对您的学习有所帮助!

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

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

相关文章

【matlab】将程序打包为exe文件(matlab r2023a为例)

文章目录 一、安装运行时环境1.1 安装1.2 简介 二、打包三、打包文件为什么很大 一、安装运行时环境 使用 Application Compiler 来将程序打包为exe&#xff0c;相当于你使用C编译器把C语言编译成可执行程序。 在matlab菜单栏–App下面可以看到Application Compiler。 或者在…

啤酒过滤——关于过滤助剂的介绍

在啤酒的酿造过程中&#xff0c;过滤是一个关键步骤&#xff0c;在啤酒厂中最常用的过滤助剂主要有两种&#xff1a;硅藻土和珍珠岩。它们能够帮助去除杂质&#xff0c;确保啤酒的清澈和口感。过滤助剂通常以粉状形式存在&#xff0c;它们被涂抹在过滤机的支撑材料上&#xff0…

深度合成算法备案和大模型备案的区别是什么

以下是关于大语言模型上线备案和深度合成算法备案区别的文档内容&#xff1a; 一、大语言模型上线备案与深度合成算法备案的区别 备案对象 大语言模型上线备案&#xff1a;主要针对生成式人工智能&#xff08;AIGC&#xff09;产品中的大型语言模型&#xff0c;能够生成文本、图…

MT6765/MT6762(R/D/M)/MT6761(MT8766)安卓核心板参数比较_MTK联发科4G智能模块

联发科Helio P35 MT6765安卓核心板 MediaTek Helio P35 MT6765是智能手机的主流ARM SoC&#xff0c;于2018年末推出。它在两个集群中集成了8个ARM Cortex-A53内核&#xff08;big.LITTLE&#xff09;。四个性能内核的频率高达2.3GHz。集成显卡为PowerVR GE8320&#xff0c;频率…

MATLAB系列09:图形句柄

MATLAB系列09&#xff1a;图形句柄 9. 图形句柄9.1 MATLAB图形系统9.2 对象句柄9.3 对象属性的检测和更改9.3.1 在创建对象时改变对象的属性9.3.2 对象创建后改变对象的属性 9.4 用 set 函数列出可能属性值9.5 自定义数据9.6 对象查找9.7 用鼠标选择对象9.8 位置和单位9.8.1 图…

Leetcode面试经典150题-39.组合总数进阶:40.组合总和II

本题是扩展题&#xff0c;真实考过&#xff0c;看这个题之前先看一下39题 Leetcode面试经典150题-39.组合总数-CSDN博客 给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数…

E2VPT: An Effective and Efficient Approach for Visual Prompt Tuning

论文汇总 存在的问题 1.以前的提示微调方法那样只关注修改输入&#xff0c;而应该明确地研究在微调过程中改进自注意机制的潜力&#xff0c;并探索参数效率的极限。 2.探索参数效率的极值来减少可调参数的数量? 解决办法 提示嵌入进行transformer中 提示剪枝 Token-wise …

004_动手实现MLP(pytorch)

import torch from torch import nn from torch.nn import init import numpy as np import sys import d2lzh_pytorch as d2l # 1.数据预处理 mnist_train torchvision.datasets.FashionMNIST(root/Users/w/PycharmProjects/DeepLearning_with_LiMu/datasets/FashionMnist, t…

DevExpress WPF中文教程:如何解决行焦点、选择的常见问题?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

0-1开发自己的obsidian plugin DAY 2

今天上午解决了三个问题 1. typescript长得丑/一片飘红/格式检查太严格 在vscode的settings里搜索下面这个然后false掉&#xff1a; "typescript.validate.enable": false 就不会一片飘红了&#xff08;其他下载第三方插件如TSLint和typescript hero的方法都不好使&…

虚幻引擎的三种输入模式和将控件显示到屏幕上

首先要知道一个概念 , HUD 和 Input 都是由 PlayerController 来控制的 而虚幻的Input控制模式有三种 Set Input Mode Game Only (设置输入模式仅限游戏): 视角会跟着鼠标旋转 , 就是正常游戏的模式 , 这也是游戏默认输入模式 Set Input Mode UI Only (设置输入模式仅限UI): …

DHCP协议原理(网络协议)

DHCP简介 定义 DHCP&#xff08;动态主机配置协议&#xff09;是一种网络管理协议&#xff0c;能够自动为局域网中的每台计算机分配IP地址及其他网络配置参数&#xff0c;包括子网掩码、默认网关和DNS服务器等。这一机制极大简化了网络管理&#xff0c;尤其在大型局域网中&am…

sheng的学习笔记-AI-K-摇臂赌博机(K-armed bandit)

AI目录&#xff1a;sheng的学习笔记-AI目录-CSDN博客 强化学习 sheng的学习笔记-AI-强化学习&#xff08;Reinforcement Learning, RL&#xff09;-CSDN博客 基础知识 单步强化学习任务 先考虑比较简单的情形&#xff1a;最大化单步奖赏&#xff0c;即仅考虑一步操作。需注意…

使用API有效率地管理Dynadot域名,注册域名服务器(NS)信息

前言 Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮箱&…

GPU共享技术深度剖析与总结

在人工智能和深度学习领域&#xff0c;GPU&#xff08;图形处理器&#xff09;已成为不可或缺的计算工具。随着深度学习模型的规模和复杂性的增加&#xff0c;单个GPU已经难以满足所有训练需求&#xff0c;GPU共享技术应运而生&#xff0c;成为提高训练效率的重要手段。本文将深…

聊聊AUTOSAR:基于Vector MICROSAR的TC8测试开发方案

技术背景 车载以太网技术作为汽车智能化和网联化的重要组成部分&#xff0c;正逐步成为现代汽车网络架构的核心&#xff0c;已广泛应用于汽车诊断&#xff08;如OBD&#xff09;、ECU软件更新、智能座舱系统、高清摄像头环视泊车系统等多个领域。 在这个过程中&#xff0c;ET…

oklink爬虫逆向分析

目标网站 aHR0cHM6Ly93d3cub2tsaW5rLmNvbS96aC1oYW5zL2tsYXl0bi9ibG9jay1saXN0L3BhZ2UvMg 一、抓包分析 请求头有很多加密参数&#xff0c;不过经过观察&#xff0c;发现只有X-Apikey是检测的 二、逆向分析 发包类型不是XMLHttpRequest&#xff0c;不能下xhr断点 打开启动器…

【项目案例】物联网比较好的10+练手项目推荐,附项目文档/源码/视频

练手项目推荐 1 智能小车 项目功能介绍&#xff1a; 本项目由三部分组成&#xff1a;应用端&#xff08;微信小程序&#xff09;、设备端&#xff08;Hi3861&#xff09;、驱动端&#xff08;UPS&#xff09;。 1. 应用端&#xff0c;采用微信小程序作为应用端控制界面。在开…

spring里面内置的非常实用的工具

一 、请求数据记录 Spring Boot提供了一个内置的日志记录解决方案&#xff0c;通过 AbstractRequestLoggingFilter 可以记录请求的详细信息。 AbstractRequestLoggingFilter 有两个不同的实现类&#xff0c;我们常用的是 CommonsRequestLoggingFilter。 通过 CommonsRequestL…

CSS | 如何来避免 FOUC(无样式内容闪烁)现象的发生?

一、什么是 FOUC(无样式内容闪烁)? ‌FOUC&#xff08;Flash of Unstyled Content&#xff09;是指网页在加载过程中&#xff0c;由于CSS样式加载延迟或加载顺序不当&#xff0c;导致页面出现闪烁或呈现出未样式化的内容的现象。‌ 这种现象通常发生在HTML文档已经加载&…