sizeof和strlen

sizeof

sizeof是用来计算变量所占内存空间大小的,单位是字节,如果操作数是类型,计算的是使用类型创建的变量所占内存空间的大小。

sizeof只关注占用内存空间的大小,不在乎内存中存放什么数据。

我们来看一下这个代码,它的运行结果是多少?

#include<stdio.h>
int main()
{int a = 10;printf("%zu\n", sizeof(a + 3.14));return 0;
}

a是int类型的数据,3.14是double类型的数据,两者进行运算时,会将int类型的数据提升为double类型,所以最后结果的类型是double类型,所以最后结果应该是8.

strlen()

strlen 是 C 语言库函数,功能是求字符串长度。函数原型如下:

 size_t strlen (const char * str);

统计的是从 strlen 函数的参数 str 中这个地址所指向的元素开始向后找,直到\0 之前字符串中字符的个数。
strlen 函数会一直向后找 \0 字符,直到找到为止,所以可能存在越界查找。

看以下代码,运行结果啥?

#include <stdio.h>
#include <string.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(arr2));return 0;
}

arr1是一个字符数组,末尾没有'\0',而strlen会一直向后找'\0',直到找到,所以使用strlen(arr1)的结果应该是一个随机值。

arr2是一个字符串,字符串的末尾含有'\0',所以strlen(arr2)的结果为3。

我们之前说过,sizeof(数组名)中,数组名表示整个数组,计算结果使整个数组的大小。

所以,sizeof(arr1)=3,sizeof(arr2)=4.

sizeof和strlen对比

sizeofstrlen
1. sizeof 是操作符
2. sizeof 计算操作数所占内存的大小,单位是字节
3. 不关注内存中存放什么数据
1. strlen 是库函数,使用需要包含头文件 string.h
2. strlen 是求字符串长度的,统计的是 \0 之前字符的个数
3. 关注内存中是否有 \0,如果没有 \0,就会持续往后找,可能会越界

数组和指针试题

在此之前,还是提醒一下大家:

数组名的意义

  1. sizeof (数组名),数组名单独放在sizeof()中,这里的数组名表示整个数组,计算的是整个数组的大小。
  2. & 数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址。
  • 题目1:下面代码的运行结果
int main()
{int a[] = { 1,2,3,4 };printf("%zu\n", sizeof(a));printf("%zu\n", sizeof(a + 0));printf("%zu\n", sizeof(*a));printf("%zu\n", sizeof(a + 1));printf("%zu\n", sizeof(a[1]));printf("%zu\n", sizeof(&a));printf("%zu\n", sizeof(*&a));  printf("%zu\n", sizeof(&a + 1));printf("%zu\n", sizeof(&a[0]));printf("%zu\n", sizeof(&a[0] + 1));   return 0;
}

解释:

16     //数组名单独放在sizeof()中,所以计算的是整个数组的大小,结果是4*4=16
8/4    //这里的数组名并没有单独放在sizeof()中,表示的是首元素的地址,a+0表示地址偏移量为0,所以表示的是首元素的地址,结果是指针的大小,即4/8
4       //这里的数组名并没有单独放在sizeof()中,表示首元素的地址,*a得到首元素a[0],这是一个整型变量,大小为4个字节
8/4    //a没有单独放在sizeof()中,表示首元素的地址,a+1表示地址偏移量为1,所以表示的是第二个元素的地址,结果是指针的大小,即4/8
4     //a[1]表示的是数组里面的整型元素,故结果为4
8/4  //&a取出的是整个数组的地址,既然是地址,那就是指针类型的数据,指针大小都是4/8
16   //&a取出的是整个数组的地址,那么它的类型就是数组指针:int(*)[4],那么对&a进行解引用,得到的就是整个数组,整个数组的大小自然就是16
8/4  //&a取出的是整个数组的地址,那么它的类型就是数组指针,&a+1表示要跳过整个数组的大小,但它的类型还是指针,所以结果为4/8
8/4  //a[0]是整型变量,它的地址类型就是整型指针,指针的大小就是4/8
8/4 //&a[0]是第一个元素的地址,&arr[0]+1表示的是第二个元素的地址,指针的大小就是4/8

  • 题目2:下面代码的运行结果
#include <stdio.h>
int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", sizeof(arr));printf("%d\n", sizeof(arr + 0));printf("%d\n", sizeof(*arr));printf("%d\n", sizeof(arr[1]));printf("%d\n", sizeof(&arr));printf("%d\n", sizeof(&arr + 1));printf("%d\n", sizeof(&arr[0] + 1));return 0;
}

这道题跟上面那道题做法几乎相同,我们再来看一下:

6      //数组名单独放在sizeof()中,所以计算的是整个数组的大小,结果是1*6=6
8/4   //这里的数组名并没有单独放在sizeof()中,表示的是首元素的地址,arr+0表示地址偏移量为0,所以表示的是首元素的地址,结果是指针的大小,即4/8
1     //这里的数组名并没有单独放在sizeof()中,表示首元素的地址,*a得到首元素a[0],这是一个整型变量,大小为1个字节
1    //arr[1]表示的是数组里面的整型元素,故结果为1
8/4  //&arr取出的是整个数组的地址,既然是地址,那就是指针类型的数据,指针大小都是              4/8
8/4  //&arr取出的是整个数组的地址,那么它的类型就是数组指针,&a+1表示要跳过整个数组的大小,但它的类型还是指针,所以结果为4/8
8/4   //&arr[0]是第一个元素的地址,&arr[0]+1表示的是第二个元素的地址,指针的大小就是             4/8

  • 题目3:下面代码的运行结果
#include <stdio.h>
#include <string.h>int main()
{char arr[] = { 'a','b','c','d','e','f' };
//1.printf("%zu\n", strlen(arr));
//2.printf("%zu\n", strlen(arr + 0));
//3.printf("%zu\n", strlen(*arr));
//4.printf("%zu\n", strlen(arr[1]));
5.printf("%zu\n", strlen(&arr));
6.printf("%zu\n", strlen(&arr + 1));
7.printf("%zu\n", strlen(&arr[0] + 1));return 0;
}

解释:

//这个字符串中没有\0,strlen就会持续往后找\0,就会越界,所以结果是随机值

//arr和arr+0表示的都是首元素的地址,所以在同一测试环境行下,这和第一个结果一样,都是随机值

//*arr表示的是首元素a,a的ASCII码值是97,是一个整型,但是strlen需要接收的是一个字符指针类型的地址,所以会把97当成一个地址,但这块地址可能不属于当前内存,这就造成了非法访问,导致程序崩溃,如果要继续测试下面的代码,就要注释掉这句代码

//和第三个结果一样,会导致程序崩溃,如果要继续测试下面的代码,就要注释掉这句代码

//&arr的类型是数组指针类型:char(*)[],但是它里面存放的值和arr是一样的,而strlen需要接受的是char*类型的指针,所以会把&arr的结果当做char*类型来处理,所以在同一测试环境行下,这和第一个结果一样,都是随机值

//&arr+1表示跳过了整个字符数组,也就是跳过了6个字符元素,但它的类型仍然和&arr类型相同,而strlen需要接受的是char*类型的指针,所以会把&arr+1的结果当做char*类型来处理,然后往后找\0,所以结果是随机值,而且在同一测试环境行下,这和第一个结果相差6(整个字符数组的大小)

//&arr[0]+1表示的是第二个元素的地址,这个字符串中没有\0,strlen就会持续往后找\0,就会越界,所以结果是随机值,而且在同一测试环境行下,这和第一个结果相差1

  • 题目4:下面代码的运行结果
#include <stdio.h>
int main()
{char arr[] = "abcdef";printf("%zu\n", sizeof(arr));//printf("%zu\n", sizeof(arr + 0));printf("%zu\n", sizeof(*arr));printf("%zu\n", sizeof(arr[1]));printf("%zu\n", sizeof(&arr));printf("%zu\n", sizeof(&arr + 1));printf("%zu\n", sizeof(&arr[0] + 1));return 0;
}

这个代码的结果分析与前面代码的分析一样,我们就不再赘述,如果有不懂的,欢迎在评论区留言哦。这里我们直接给出答案:

7
8/4
1
1
8/4
8/4
8/4

  • 题目5:下面代码的运行结果
#include <stdio.h>
#include <string.h>
int main()
{char arr[] = "abcdef";printf("%zu\n", strlen(arr));printf("%zu\n", strlen(arr + 0));printf("%zu\n", strlen(*arr));printf("%zu\n", strlen(arr[1]));printf("%zu\n", strlen(&arr));printf("%zu\n", strlen(&arr + 1));printf("%zu\n", strlen(&arr[0] + 1));return 0;
}

//arr表示首元素的地址,由于这是字符串,末尾隐藏着一个\0,所以计算的是\0之前的字符个数,结果是6

//arr+0表示首元素的地址,由于这是字符串,末尾隐藏着一个\0,所以计算的是\0之前的字符个数,结果是6

//和题目三中结果一样,会导致程序崩溃

//会导致程序崩溃

//&arr的类型是数组指针类型,但是它里面存放的值和arr是一样的,而strlen需要接受的是char*类型的指针,所以会把&arr的结果当做char*类型来处理,所以在同一测试环境行下,这和第一个结果一样

//&arr+1表示跳过了整个字符数组,也就是跳过了7个字符元素,但它的类型仍然和&arr类型相同,而strlen需要接受的是char*类型的指针,所以会把&arr+1的结果当做char*类型来处理,然后往后找\0,所以结果是随机值

//&arr[0]+1表示第二个元素的地址,所以结果比第一个的少1,即结果是5

  • 题目6:下面代码的运行结果
#include <stdio.h>
int main()
{char* p = "abcdef";printf("%zu\n", sizeof(p));printf("%zu\n", sizeof(p + 1));printf("%zu\n", sizeof(*p));printf("%zu\n", sizeof(p[0]));printf("%zu\n", sizeof(&p));printf("%zu\n", sizeof(&p + 1));printf("%zu\n", sizeof(&p[0] + 1));return 0;
}

解释:

8/4     //p是指针变量,里面存放的是a的地址,所以结果是8/4
8/4     //p+1仍然是指针,里面存放的是b的地址,所以结果是8/4
1       //*p的结果是a,a是字符型变量,所以结果是1
1      //p[0]等价于*(p+0),得到的是a,所以结果是1
8/4     //&p是二级指针,也是地址,所以结果是4/8
8/4     //&p+1仍然是指针,所以结果是4/8
8/4     //&p[0]+1表示的是b的地址,所以结果是4/8

  • 题目7:下面代码的运行结果
#include <stdio.h>
#include <string.h>
int main()
{char* p = "abcdef";printf("%zu\n", strlen(p));printf("%zu\n", strlen(p + 1));printf("%zu\n", strlen(*p));printf("%zu\n", strlen(p[0]));printf("%zu\n", strlen(&p));printf("%zu\n", strlen(&p + 1));printf("%zu\n", strlen(&p[0] + 1));return 0;
}

//strlen会往p所指向的那块内存先后找,直到找到\0,所以结果是6

//p+1指向元素b,所以结果是5

//*p得到a,a的ASCII码值是97,strlen会把这个数值当成一个指针,但这个地址不一定在当前程序内,也不一定存在,就造成了非法访问,引起程序崩溃

//p[0]等价于*p,结果与上面一样

//&p是二级指针,strlen会往&p所指向的那块内存先后找,直到找到\0,但是不知道\0在那块空间的位置,所以结果是随机值

//和上面一样,结果是随机值,但是这里有一个问题,strlen(&p)和strlen(&p+1)的结果是否有关系呢?答案是没有关系,因为你不知道从p往后找是否能在走完p所对应的内存之前找到\0

//&p[0]+1表示b的地址,所以结果是5

  • 题目8:下面代码的运行结果
#include <stdio.h>
int main()
{int a[3][4] = { 0 };printf("%zu\n", sizeof(a));printf("%zu\n", sizeof(a[0][0]));printf("%zu\n", sizeof(a[0]));printf("%zu\n", sizeof(a[0] + 1));printf("%zu\n", sizeof(*(a[0] + 1)));printf("%zu\n", sizeof(a + 1));printf("%zu\n", sizeof(*(a + 1)));printf("%zu\n", sizeof(&a[0] + 1));printf("%zu\n", sizeof(*(&a[0] + 1)));printf("%zu\n", sizeof(*a));printf("%zu\n", sizeof(a[3]));return 0;
}

解析:

     二维数组是元素为一维数组的数组

48 //a是数组名,数组名单独放在sizeof()中,计算的是整个数组的大小,所以结果是4*12=48
4  //a[0][0]表示的是数组中的整型元素,所以结果是4
16  //a[0]表示的是第一行一维数组的数组名,数组名单独放在sizeof中,计算的是整个数组的大小,所以结果是4*4=16
4/8   //a[0]表示第一行一维数组的数组名,数组名并没有单独放在sizeof中,所以表示的是第一行一维数组首元素的地址,所以a[0]+1表示的是第二个元素的地址,既然是地址,那大小就是4/8
4   //a[0]+1表示的是第一行的一维数组中第二个元素的地址,那么*(a[0]+1)就是访问数组中元素,所以结果为4
4/8  //a表示二维数组的数组名,数组名并没有单独放在sizeof中,表示的是第一行一维数组的地址,a+1表示要跳过第一行整个一维数组,指向第二行,即表示第二行一维数组的地址,既然是地址,那大小就是4/8
16  //a+1表示第二行一维数组的地址,*(a+1)表示访问整个一维数组,既然是访问整个一维数组,结果自然是4*4=16(也可以这么理解:*(a+1)等价于a[1],a[1]表示的是第二行一维数组的数组名,数组名单独放在sizeof中,结果就是计算这个一维数组的大小)
4/8   //a[0]表示第一行一维数组的数组名,前面有&,取出的是整个一维数组的地址,所以&arr[0]+1表示跳过第一行整个一维数组,指向第二行整个一维数组,既然还是地址,那么结果就是4/8
16   //&a[0]+1表示第二行整个一维数组的地址,对它进行解引用,访问的是整个一维数组,所以结果是16
16    //a表示二维数组的数组名,数组名并没有单独放在sizeof中,表示的是第一行一维数组的地址,对这个地址进行解引用,访问的是整个一维数组,所以结果是16(也可以这么理解:*a等价于*(a+0)等价于a[0],表示的是第一行一维数组的数组名,数组名单独放在sizeof中,访问的是整个数组,所以结果是16)
16   //看到这个代码,想必很多小伙伴都认为这个包会报错的,毕竟,这不是越界访问了吗?但是,我们说过,sizeof在计算变量大小的时候,是通过类型求推导的,所以他并不会真正去访问内存,既然没有越界访问内存,那不就不会报错了,而在根据类型推导sizeof(a[3])的大小时,会将a[0]和a[3]是同等类型的,所以结果自然是16了

指针运算试题

  • 题目1:下面代码的运行结果
#include <stdio.h>
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int* ptr = (int*)(&a + 1);printf("%d, %d", *(a + 1), *(ptr - 1));return 0;
}

解析:a是数组名,一般情况下表示首元素的地址,a+1表示跳过一个整型的大小,所以a+1指向第二个元素,则*(a+1)得到的是2;&a取出的是整个数组的的地址,所以&a+1会跳过整个整形数组,如图,将这个地址转换成整型指针的地址以后赋给ptr,ptr指向如图所示,ptr-1会向前走过一个整形大小的步长,如图所示,所以*(ptr-1)得到的是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;
}

解析:在定义结构体的同时创建了结构体指针变量p,并将0X100000强制类型转换成结构体指针类型以后赋值给p,p+0x1也就是p+1,p所指向的变量为结构体类型,所以p+1需要跳过20个字节,所以p+1=0x100020,等等,这对吗?注意咯,这里是十六进制的形式,逢十六进一,所以结果应该是0x100014,而在X86环境下,会将地址的8位都打印出来,且不会省略掉前面的0,所以结果是00100014.

将p强制类型转换成unsigned long类型以后,里面的值就是一个0x100000,加上一后就是普通的整型相加,所以结果是0X100001,在X86环境下的打印结果是0X100001

将p强制类型转换成unsigned int*类型以后,对指针+1会跳过4个字节,所以结果就是0X100004,在X86环境下,结果就是00100004

  • 题目3:下面代码的运行结果
#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int* p;p = a[0];printf("%d", p[0]);return 0;
}

解析:我们先要搞清楚数组里面放了啥,数组里面放的是0,1,2,3,4,5嘛?看着好像是的。注意啦兄弟们,数组里面用括号括起来的是逗号表达式哦,所以数组里面的元素应该是{1,3,5,0,0,0}。

弄清这个以后,我们再来看指针。p是一个整形指针,a[0]是第一行那个一维数组的数组名,一般情况下,他表示首元素的地址,也就是说p里面存放的是第一行一维数组首元素的地址,p[0]等价于*(p+0),p+0还是表示第一行一维数组首元素的地址,对它进行解引用,访问的就是第一行一维数组的首元素,也就是1,所以打印结果是1.

  • 题目4:下面代码的运行结果
#include <stdio.h>
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表示的是二维数组的名称,一般情况下,数组名表示首元素的地址,则aa表示第一行一维数组的地址,aa+1表示跳过整个一维数组,则aa+1指向第二行整个一维数组;&aa取出的是整个二位数组的地址,&aa+1跳过的是整个二维数组,由此,可得图中各指针指向的由来。

ptr1和ptr2都是整型指针,+1时跳过一个整形元素的步长,-1时向前走一个整形元素的步长,所以得到相应指向,对指针解引用以后可以得到打印结果是:10,5

  • 题目5:下面代码的运行结果
//假设环境是x86环境,程序输出的结果是啥?
#include <stdio.h>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;
}

图示解析:

  • 题目6:下面代码的运行结果
#include <stdio.h>
int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}

图示解析:

  • 题目7:下面代码的运行结果
#include <stdio.h>
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;
}

图示解析:

运行结果:

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

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

相关文章

华为云 Flexus 部署 coze-studio

华为云 Flexus 部署 coze-studio 一、前置 主机和程序&#xff1a;云主机&#xff08;Flexus L ubuntu&#xff09; coze-studio 部署方式&#xff1a;docker&#xff08;提前装好的&#xff09; 字节跳动开源AI智能体开发平台Coze&#xff0c;具备极低的硬件门槛——2核CPU…

Linux系统编程Day7 -- 基于Linux系统知识的第一个程序

往期内容回顾 自动化构建工具-make/Makefile gcc/g编译及链接 Vim工具的使用 Linux常用工具&#xff08;yum与vim&#xff09; ​​​​​​ Linux系统编程Day4-- Shell与权限 编写第一个Linux程序 今天我们要利用我们所学到的Linux语言来编译第一个Linux程序&#xff0c;在进行…

安卓264和265编码器回调编码数据写入.265或者.264文件、查看编码数据是否正确、转换为Mp4文件、查看Mp4文件信息等方法合集

一、写入文件 1、变量定义 private FileOutputStream m265FileOutputStream null; private File m265File null; private static final String HEVC_265_FILE_NAME "output.265"; // 或 .265 private static final String AVC_264_FILE_NAME "output.264&qu…

如何打造一支AI时代下的IT团队,为企业战略目标快速赋能

执行摘要 在当前AI技术迅猛发展的背景下&#xff0c;中国中小企业正面临着前所未有的数字化转型机遇与挑战。据最新调研显示&#xff0c;2025年全球AI市场规模将突破5000亿美元&#xff0c;而中国AI应用占比已达35%。与此同时&#xff0c;AI领域人才缺口高达1000万人&#xff0…

机器学习-LinearRegression

1、 关键数学知识点&#xff1a; 边缘概率密度 联合密度对非关注变量积分&#xff1a;fX(x)∫fX,Y(x,y)dyf_X(x)∫f_{X,Y}(x,y)dyfX​(x)∫fX,Y​(x,y)dy&#xff1b; 条件概率密度 切片 fX∣Y(x∣y)fX,Y(x,y)/fY(y)f_{X|Y}(x|y)f_{X,Y}(x,y)/f_Y(y)fX∣Y​(x∣y)fX,Y​(x,y)…

解决微信小程序中如何把npm构建的模块与主包分离,构建到分包上面

1、配置分包2、复制packge.json到分包中3、在project.config.json中增加npm配置4、终端执行npm i下载模块5、构建npm到miniprogram_npm中

自动驾驶中的传感器技术21——Camera(12)

自动驾驶摄像头的图像评测 摄像头的性能受到环境光照、天气条件、运动模糊等因素的影响&#xff0c;因此需要通过多方面的评测来确保其在各种场景下的可靠性。 在自动驾驶领域&#xff0c;图像质量评估不仅关注图像的清晰度、分辨率等传统指标&#xff0c;还需要结合目标检测…

AI+OA原生应用 麦当秀AIPPT

麦当秀也在WAIC期间重新定义AIOA一、什么是“原生AI”&#xff1f;“原生AI”可以理解为&#xff1a;AI系统本身具备完整的办公能力&#xff0c;不需要依赖传统办公软件&#xff08;如Word、Excel、PPT&#xff09;作为载体。也就是说&#xff0c;用户可以直接通过AI系统完成文…

K8S 入门操作

之前一直用kubectl这个命令操作&#xff0c;这些都是基于命令来操作K8S kubectl get pods kubectl get nodes kubectl get svc kubectl create deployment... kubectl expose deployment...kubectl 文档 命令行工具 (kubectl) | Kubernetes 命令参考 Kubectl Reference Doc…

蒙文OCR识别技术难点实现及应用场景剖析

一、蒙文OCR识别核心技术难点1. 文字特性带来的识别挑战连写特性&#xff1a;蒙文字符存在复杂的连写形式&#xff08;词首、词中、词尾变形&#xff09;方向特异性&#xff1a;传统蒙文为垂直书写&#xff08;现代也有横排&#xff09;&#xff0c;需特殊方向处理字符相似性&a…

通过docker构建一个java镜像

通过docker构建一个java镜像 FROM zlyxzq/centos7:v1 VOLUME /tmp WORKDIR /app COPY /target/aa.jar /root/app/aa.jarENV TZAsia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezoneENV JAVA_HOME /usr/local/java ENV PA…

SpringBoot学习日记 Day5:解锁企业级开发核心技能

一、前言&#xff1a;从玩具项目到生产系统经过前四天的学习&#xff0c;我们已经能够开发基础功能了。但要让应用真正具备生产价值&#xff0c;还需要掌握数据库高级操作、事务控制、缓存优化等企业级开发技能。今天就来攻克这些关键知识点&#xff01;二、JPA进阶&#xff1a…

将英文PDF文件完整地翻译成中文的4类方式

文章目录一、在线翻译服务&#xff08;最快捷&#xff0c;适合临时查看&#xff09;1.1 代表工具&#xff1a;1.2 操作流程&#xff08;以Google翻译为例&#xff09;1.3 优点和缺点1.4 适用场景二、专业软件&#xff08;最佳平衡&#xff0c;兼顾格式与质量&#xff09;2.1 代…

【分享】我国八大沙漠空间矢量范围

今天小编整理分享的是 我国八大沙漠空间矢量范围shp。▲ 我国八大沙漠空间矢量范围概况数据概况我国八大沙漠空间矢量范围。中国八大沙漠。分别为腾格里沙漠&#xff0c;塔克拉马干沙漠&#xff0c;巴丹吉林沙漠&#xff0c;库布奇沙漠&#xff0c;乌兰布和沙漠&#xff0c;库…

【音视频】WebRTC C++ native 编译

一、搭建环境 我们这里介绍在Windows10VS2019的环境下编译WebRTC源码&#xff0c;由于WebRTC源码在外网上&#xff0c;需要科学的方式下载&#xff0c;不然下载特别慢&#xff0c;建议直接找国内下载好的源码&#xff0c;这里的源码是2021年的版本&#xff1a;https://pan.bai…

Selenium在Pyhton应用

目录 1. selenium的基本原理 2. selenium环境的搭建步骤 3. 元素的定位和操作 4.元素的基本属性方法 5.浏览器的操作方法 6.三种等待 强制等待 显示等待 隐式等待 7. 键盘与鼠标的操作 鼠标悬停用 拖拽操作 8. 下拉框元素定位 9.页面滚动操作 10. 页面截图操作 S…

【Docker】Redis基础命令在Docker中的使用

文章目录一 Redis 容器化部署指南1 获取 Redis 镜像2 服务启动2.1 首次启动新容器2.2 重启已有容器3 服务验证4 连接 Redis5 数据持久化方案5.1 使用 Docker 卷5.2 启用 AOF 持久化6 容器管理6.1 停止容器6.2 删除容器7 数据清理7.1 清空 Redis 数据7.2 完全移除7.3 删除数据卷…

ubuntu 2024 安装拼音输入法

1. 卸载ibussudo apt remove ibus2. install fcitx5核心组件sudo apt install fcitx5 fcitx5-chinese-addons fcitx5-material-color3. 安装中文语言支持sudo apt install language-pack-zh-hans4. 设置默认输入法im-config -n fcitx55. 配置环境变量sudo vim ~/.bashrc粘贴&am…

语言模型的多个agent

是的&#xff0c;语言模型 在某些情况下确实可以通过多个 agent&#xff08;代理&#xff09;来共同协作完成任务。这种设计通常用于复杂任务或需要多步骤处理的场景&#xff0c;具体的流程如下&#xff1a; 1. 什么是 Agent&#xff1f; Agent&#xff08;代理&#xff09; 是…

CSS--:root指定变量,其他元素引用

原文网址&#xff1a;CSS--:root指定变量&#xff0c;其他元素引用-CSDN博客 简介 本文介绍CSS中使用变量的方法。 场景描述 CSS可以使用变量&#xff0c;比如&#xff1a;指定整个网页的主体颜色作为变量&#xff0c;其他的元素去使用这个颜色。这样在修改颜色时&#xff…