指针(5)

news2024/12/25 15:56:35

前言

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

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));			//1
	printf("%d\n", sizeof(a + 0));		//2
	printf("%d\n", sizeof(*a));			//3
	printf("%d\n", sizeof(a + 1));		//4
	printf("%d\n", sizeof(a[1]));		//5
	printf("%d\n", sizeof(&a));			//6
	printf("%d\n", sizeof(*&a));		//7
	printf("%d\n", sizeof(&a + 1));		//8
	printf("%d\n", sizeof(&a[0]));		//9
	printf("%d\n", sizeof(&a[0] + 1));	//10
	return 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));		//1
	printf("%d\n", sizeof(arr + 0));	//2
	printf("%d\n", sizeof(*arr));		//3
	printf("%d\n", sizeof(arr[1]));		//4
	printf("%d\n", sizeof(&arr));		//5
	printf("%d\n", sizeof(&arr + 1));	//6
	printf("%d\n", sizeof(&arr[0] + 1));//7
	return 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));		//1
	printf("%d\n", strlen(arr + 0));	//2
	printf("%d\n", strlen(*arr));		//3
	printf("%d\n", strlen(arr[1]));		//4
	printf("%d\n", strlen(&arr));		//5
	printf("%d\n", strlen(&arr + 1));	//6
	printf("%d\n", strlen(&arr[0] + 1));//7
	return 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));		//1
	printf("%d\n", sizeof(arr + 0));	//2
	printf("%d\n", sizeof(*arr));		//3
	printf("%d\n", sizeof(arr[1]));		//4
	printf("%d\n", sizeof(&arr));		//5
	printf("%d\n", sizeof(&arr + 1));	//6
	printf("%d\n", sizeof(&arr[0] + 1));//7
	return 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));		//1
	printf("%d\n", strlen(arr + 0));	//2
	printf("%d\n", strlen(*arr));		//3
	printf("%d\n", strlen(arr[1]));		//4
	printf("%d\n", strlen(&arr));		//5
	printf("%d\n", strlen(&arr + 1));	//6
	printf("%d\n", strlen(&arr[0] + 1));//7
	return 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));			//1
	printf("%d\n", sizeof(p + 1));		//2
	printf("%d\n", sizeof(*p));			//3
	printf("%d\n", sizeof(p[0]));		//4
	printf("%d\n", sizeof(&p));			//5
	printf("%d\n", sizeof(&p + 1));		//6
	printf("%d\n", sizeof(&p[0] + 1));	//7
	return 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));			//1
	printf("%d\n", strlen(p + 1));		//2
	printf("%d\n", strlen(*p));			//3
	printf("%d\n", strlen(p[0]));		//4
	printf("%d\n", strlen(&p));			//5
	printf("%d\n", strlen(&p + 1));		//6
	printf("%d\n", strlen(&p[0] + 1));	//7
	return 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));				//1
	printf("%d\n", sizeof(a[0][0]));		//2
	printf("%d\n", sizeof(a[0]));			//3
	printf("%d\n", sizeof(a[0] + 1));		//4
	printf("%d\n", sizeof(*(a[0] + 1)));	//5
	printf("%d\n", sizeof(a + 1));			//6
	printf("%d\n", sizeof(*(a + 1)));		//7
	printf("%d\n", sizeof(&a[0] + 1));		//8
	printf("%d\n", sizeof(*(&a[0] + 1)));	//9
	printf("%d\n", sizeof(*a));				//10
	printf("%d\n", sizeof(a[3]));			//11
	return 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.coloradmin.cn/o/1621569.html

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

相关文章

智慧火电厂合集 | 数字孪生助推能源革命

火电厂在发电领域中扮演着举足轻重的角色。主要通过燃烧如煤、石油或天然气等化石燃料来产生电力。尽管随着可再生能源技术的进步导致其比重有所减少&#xff0c;但直至 2023 年&#xff0c;火电依然是全球主要的电力来源之一。 通过图扑软件自主研发 HT for Web 产品&#xf…

百度智能云千帆 ModelBuilder 技术实践系列:通过 SDK 快速构建并发布垂域模型

​百度智能云千帆大模型平台&#xff08;百度智能云千帆大模型平台 ModelBuilder&#xff09;作为面向企业开发者的一站式大模型开发平台&#xff0c;自上线以来受到了广大开发者、企业的关注。至今已经上线收纳了超过 70 种预置模型服务&#xff0c;用户可以快速的调用&#x…

企业微信hook接口协议,开放平台id转企业用户id

开放平台id转企业用户id 参数名必选类型说明uuid是String每个实例的唯一标识&#xff0c;根据uuid操作具体企业微信 请求示例 {"uuid":"3240fde0-45e2-48c0-90e8-cb098d0ebe43","openid":["woO9o4EAAAUg47yCUh1mDYVh71AJ8R3w"] } …

陪诊小程序的市场潜力与发展趋势研究

随着社会的快速发展和人口老龄化的加剧&#xff0c;医疗服务需求日益增长&#xff0c;而陪诊服务作为医疗服务的重要补充&#xff0c;正逐渐受到人们的关注和青睐。陪诊小程序作为一种便捷、高效的陪诊服务平台&#xff0c;其市场潜力和发展趋势值得关注。 一、市场潜力分析 人…

【现代交换原理与通信网技术】期末突击

文章目录 自己老师画的重点1. 程控交换机结构2. 测试模拟电路的七项功能3.中继电路的六项功能4.数字用户电路和模拟用户电路比较5.路由规划的基本原则6.七路信令的结构7.随路信令和公共信道信令8.软交换9.无极网和分级网10.路由选择.流量控制的原则/方法11.电路交换&&分…

微软Phi-3,3.8亿参数能与Mixtral 8x7B和GPT-3.5相媲美,量化后还可直接在IPhone中运行

Phi-3系列 Phi-3是一系列先进的语言模型&#xff0c;专注于在保持足够紧凑以便在移动设备上部署的同时&#xff0c;实现高性能。Phi-3系列包括不同大小的模型&#xff1a; Phi-3-mini&#xff08;38亿参数&#xff09; - 该模型在3.3万亿个令牌上进行训练&#xff0c;设计得足…

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域

解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务&#xff08;Spring MVC Springboot&#xff09;同时允许跨域 Tomcat 配置允许跨域Web 项目配置允许跨域Tomcat 同时允许静态文件和 Web 服务跨域 偶尔遇到一个 Tomcat 部署项目跨域问题&#xff0c;因为已经处理过…

如何调节电脑屏幕亮度?让你的眼睛更舒适!

电脑屏幕亮度的调节对于我们的视力保护和使用舒适度至关重要。不同的环境和使用习惯可能需要不同的亮度设置。可是如何调节电脑屏幕亮度呢&#xff1f;本文将介绍三种不同的电脑屏幕亮度调节方法&#xff0c;帮助您轻松调节电脑屏幕亮度&#xff0c;以满足您的需求。 方法1&…

超级好看动态视频官网源码

源码介绍 超级好看动态视频引导页源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果截图 源码下载 超级好看动态…

4.26日学习记录

[湖湘杯 2021 final]Penetratable SUID提权 SUID是一种对二进制程序进行设置的特殊权限&#xff0c;可以让二进制程序的执行者临时拥有属主的权限 SUID具有一定的限制&#xff1a; 1.仅对于二进制有效&#xff1b; 2.执行者在程序中有可以执行的权限&#xff1b; 3.权限仅在程序…

2024腾讯游戏安全技术竞赛-机器学习赛道

决赛赛题链接https://gss.tencent.com/competition/2024/doc/2024%E8%85%BE%E8%AE%AF%E6%B8%B8%E6%88%8F%E5%AE%89%E5%85%A8%E6%8A%80%E6%9C%AF%E7%AB%9E%E8%B5%9B-%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E5%86%B3%E8%B5%9B.zip 今年的题目是游戏跨语言恶意内容识别 ,题目比较…

C++核心编程——4.5 运算符重载

4.5.0 运算符重载概念 对已有的运算符重新进行定义&#xff0c;赋予其另一种功能&#xff0c;以适应不同的数据类型 4.5.1 加号运算符重载 作用&#xff1a;实现两个自定义数据类型相加的运算 class Person { public:Person() {};Person(int a, int b){this->m_A a;this…

如何设计一个安全的系统架构?

本文转自 公众号 ByteByteGo&#xff0c;如有侵权&#xff0c;请联系&#xff0c;立即删除 如何设计一个安全的系统架构&#xff1f; 如何设计安全的系统&#xff1f;我们总结了 12 条原则供架构师们参考。 设计安全的系统非常重要&#xff0c;原因有很多&#xff0c;从保护敏…

大模型预训练Pretrain

选基座 —> 扩词表 —> 采样&切分数据 —> 设置学习参数 —> 训练 —> 能力测评&#xff09; 基座google/flan-t5 T5 模型&#xff1a;NLP Text-to-Text 预训练模型超大规模探索 - 知乎相信大多 NLP 相关者&#xff0c;在时隔 BERT 发布近一年的现在&…

阿斯达年代记三强争下载教程 阿斯达年代记游戏下载教程

《阿斯达年代记三强争霸》作为一款蔚为壮观的MMORPG巨制&#xff0c;是由Netmarble与STUDIO DRAGON携手推出的扛鼎之作&#xff0c;预计于4月24日迎来万众瞩目的公开测试。游戏的中心舞台聚焦于阿斯达大陆的统治权争夺&#xff0c;通过三大阵营——阿斯达联邦、亚高同盟与边缘叛…

excel相同行不同列查询

EXCEL中e列和f列是每一行对应的&#xff0c;我想在d列中找和e列一样的元素&#xff0c;然后获取同一行中f列的值 IFERROR(VLOOKUP(D1, E:F, 2, FALSE), "")

SpringCloud 与 Dubbo 的区别详解

一、Spring Cloud 和 Dubbo 的概述 1.1 SpringCloud 简介 SpringCloud 是一个用于构建云原生应用的框架集合&#xff0c;它为开发者提供了一套完整的工具链&#xff0c;用于快速搭建分布式系统。SpringCloud 基于 SpringBoot 开发&#xff0c;具有如下特点&#xff1a; 提供…

error while loading shared libraries: libaio.so.1: wrong ELF class: ELFCLASS32

这个错误的意思是编译对象需要32位的libaio库 centos版本执行以下命令检查系统有哪些libaio的版本 yum list libaio 如图&#xff0c;有两个版本&#xff0c;将两个版本都安装一下 yum install libaio.x86_64 再编译&#xff0c;成功

Linux下redis的安装过程与配置详细教程【5.0.5为例子】

Linux下redis的安装过程与配置方法【5.0.5为例子】 下载redis redis下载地址 https://download.redis.io/releases/ 也可以自行去官网下载 提示&#xff1a;此处安装的为redis-5.05的版本 上传redis安装包(我的安装目录为/data/tool/redis-5.0.5) 创建目录/data/local/tool并…