指针进阶(下)指针实操

sizeof 和 strlen

       首先我们来复习一下sizeof 和 strlen 的区别。
sizeof 是操作符,只关注内存中存放的数据的大小,并不会参与sizeof 括号内部的计算。注意它的单位是字节

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

由于a 是 int 类型的数据,需要的参数为指针(地址),并且 int 占四个字节的空间大小,所以上面三行的 sizeof 计算出来都是 4
我们来看一下运行的结果吧:

strlen 是 string.h 的库函数,主要是计算字符串的长度,当遇到 \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));return 0;
}

由于 strlen 遇到 \0 才会停止计算,所以计算 arr1 的长度时,由于不知道什么时候遇到 \0 所以结果是一个不确定的数(也就是随机数)
而计算 arr2 的时候,我们发现 arr2 存放的时一个字符串,也就是说 arr2 实际存储的内容为 a b c \0 这四个字符,由于 strlen 遇到 \0 就会停止计算,也就是说明最后的结果为 3

我们来看一下运行的结果吧:

数组名再深入理解

       我们知道数组名一般来说是指数组的首元素的地址,但是也有两个特殊情况:一个是 sizeof (arr) ,就是一个数组名单独放在sizeof 里面,要注意了,这里是取出的是整个数组,计算的是整个数组的大小;另外一个就是 &arr ,它取出的是整个数组的地址,那么数据类型是什么呢?举个例子:int arr [10] ,我们&arr 取出整个数组的地址,数据类型就是 int (*) [10]

#include <stdio.h>
int main()
{char arr1[3] = { 'a', 'b', 'c' };char arr2[] = "abc";printf("%d\n", sizeof(arr1));printf("%d\n", sizeof(arr2));return 0;
}

由于sizeof(数组名)计算的是整个数组的大小,也就是说我们只需要看数组占多大空间即可,arr1[3]有三个元素,每个元素的大小为 char (1个字节),总大小为 3 * 1 = 3 (字节)

arr2 没有明确说明大小,那我们需要看一下其保存的字符串的大小,也就是 a b c \0 一共有4个元素,每个元素的是 char (1个字节)总大小为 4 * 1 = 4 (字节)

我们来验证一下:

题目剖析

       这里我们通过一些题目来进一步地深入理解数组名与指针地关系。大家可以尝试自己分析一下下面代码的运行结果,然后再看一下解析。

一维数组

#include <stdio.h>int main()
{int a[] = { 1,2,3,4 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(a + 0));printf("%d\n", sizeof(*a));printf("%d\n", sizeof(a + 1));printf("%d\n", sizeof(a[1]));printf("%d\n", sizeof(&a));printf("%d\n", sizeof(*&a));return 0;
}

首先sizeof(a),数组名单独放在 sizeof 内部,计算的是整个数组的大小,也就是 4 * 4 = 16 个字节

sizeof(a+0), a+0说明数组名不是单独放在 sizeof 内部,也就是 arr 指数组首元素的地址,a+0表示跳过0个元素,还是数组首元素的地址,地址就是 4/8 个字节(64位机器地址占8个字节,32位机器地址占4个字节)

sizeof(*a) ,数组名没有单独放在sizeof 内部,就是说 a 代表的是数组首元素的地址,*a数组首元素地址的解引用操作,取出的是数组第一个元素,sizeof 计算的就是数组第一个元素的大小,也就是 4 个字节

sizeof(a+1), 数组名没有单独放在sizeof 内部,就是说 a 代表的是数组首元素的地址,a+1表示跳过一个元素,表示第二个元素的地址,既然是地址,就是 4/8 个字节的大小

sizeof(a[1]), 这个a[1] 表示数组第二个元素,也就是 4 个字节

sizeof(&a), &a 表示取出整个数组的地址,数据类型是 int (*) [4] ,既然是地址,也就是 4/8 个字节了。

我们来看一下运行结果(这里以 64 位机器为例,也就是地址大小为 8 个字节,下面的运行示例也以 64 位机器演示,就不做提醒了)

字符数组

代码一:

#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;
}

sizeof(arr), sizeof 内部单独存放数组名,计算的是整个数组的大小,数组有 6 个元素,分别为a b c d e f ;类型是 char 类型(一个字节),一共就是 6 * 1 = 6 (字节)

sizeof(arr+0), arr + 0 显而易见数组名不是单独存放再sizeof 内部,arr 表示首元素的数组名,arr + 0表示跳过0个元素,表示第一个元素的地址,既然是地址,也就是 4/8 个字节

sizeof(*arr), 数组名没有单独存放在 sizeof 内部,arr则表示为数组首元素的地址,*arr 解引用取出数组第一个元素,数据类型为 char ,即一个字节

sizeof(arr[1]),显而易见,arr[1] 取出数组第二个元素,大小为 1 个字节

sizeof(&arr), &arr表示取出整个数组的地址,地址占 4/8 个字节

sizeof(&arr+1),&arr 取出整个数组的地址,数据类型是char (*) [6] , &arr+1跳过一个数组,还是一个地址,就是 4/8 个字节

sizeof(&arr[0]+1), &arr[0] 取出的是数组首元素的地址,+1 表明跳过一个元素,指向数组第二个元素,还是一个地址, 4/8 个字节

我们来看一下运行结果:

代码二:

#include <stdio.h>
#include <string.h>int main()
{char arr[] = { 'a','b','c','d','e','f' };printf("%d\n", strlen(arr));printf("%d\n", strlen(arr + 0));printf("%d\n", strlen(*arr));printf("%d\n", strlen(arr[1]));printf("%d\n", strlen(&arr));printf("%d\n", strlen(&arr + 1));printf("%d\n", strlen(&arr[0] + 1));return 0;
}

strlen(arr),arr 表示首元素的地址,遇到 \0 才停止计算,是个随机数

strlen(arr+0),arr 表示首元素地址, arr+0表示跳过 0个元素,指向第二个元素,还是一个随机数

strlen(*arr), *arr 取出数组的首元素,strlen 需要传入地址,否则系统会报错,无法运行,硬要访问,a的ascll码值是97,访问的是地址编号为97,这是属于操作系统的是不允许访问的

strlen(arr[1]), arr[1] 取出数组第二个元素,系统报错,硬要访问,a的ascll码值是97,访问的是地址编号为97,这是属于操作系统的是不允许访问的

strlen(&arr),&arr 取出整个数组的地址,,不知道什么时候遇到 \0 ,是个随机数

strlen(&arr+1),&arr +1 取出整个数组的地址,并跳过一个数组,是个随机数

strlen(&arr[0]+1), &arr[0]+1 取出首元素的地址,跳过一个元素,指向第二个元素,是个随机数

代码三

#include <stdio.h>int main()
{char arr[] = "abcdef";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;
}

arr 存放着 a b c d e f \0 这 7 个元素

sizeof(arr),取出整个数组的大小, 7 * 1 = 7 个字节

sizeof(arr+0), arr + 0 跳过 0 个元素,指向数组第一个元素,是个地址,4/8 个字节

sizeof(*arr), *arr 表示数组首元素的解引用,取出第一个元素,1 个字节

sizeof(arr[1]), arr[1] 取出第二个元素,大小为 1 个字节

sizeof(&arr), &arr 取出整个数组的地址,数据类型是 char (*) [7] ,地址为 4/8 个字节

sizeof(&arr+1), 取出整个数组的地址,并跳过一个数组,还是一个地址,4/8 个字节

sizeof(&arr[0]+1), 取出数组首元素的地址,并跳过一个元素,指向数组的第二个元素,还是一个地址,4/8 个字节

下面是代码运行结果:

代码四

#include <stdio.h>
#include <string.h>int main()
{char arr[] = "abcdef";printf("%d\n", strlen(arr));printf("%d\n", strlen(arr + 0));printf("%d\n", strlen(*arr));printf("%d\n", strlen(arr[1]));printf("%d\n", strlen(&arr));printf("%d\n", strlen(&arr + 1));printf("%d\n", strlen(&arr[0] + 1));return 0;
}

arr 存放着 a b c d e f \0 这 7 个元素

strlen(arr),传入数组首元素的地址,遇到 \0 停下,一共就是 6

strlen(arr+0),传入数组首元素的地址,并跳过 0 个元素,还是指向数组首元素,一共是 6

strlen(*arr), *arr 取出数组首元素,不是一个地址,系统报错,硬要访问,a的ascll码值是97,访问的是地址编号为97,这是属于操作系统的是不允许访问的

strlen(arr[1]),arr[1] 取出数组第二个元素,不是一个地址,系统报错,硬要访问,b的ascll码值是98,访问的是地址编号为98,这是属于操作系统的是不允许访问的

strlen(&arr), &arr 取出整个数组的地址,还是以数组首元素的地址表示,也就是 6

strlen(&arr+1), &arr + 1 取出整个数组的地址,&arr 的数据类型是 char (*) [7] ,并跳过一个数组,也就是指向一个未知的空间,无法知道什么时候遇到 \0 ,是个随机数

strlen(&arr[0]+1),&arr[0]表示数组首元素的地址,+1 跳过一个元素,也就是从第二个元素开始计算,则为 5

代码五

#include <stdio.h>int main()
{char* p = "abcdef";printf("%d\n", sizeof(p));printf("%d\n", sizeof(p + 1));printf("%d\n", sizeof(*p));printf("%d\n", sizeof(p[0]));printf("%d\n", sizeof(&p));printf("%d\n", sizeof(&p + 1));printf("%d\n", sizeof(&p[0] + 1));return 0;
}

p 是一个字符指针,指向的是一个常量字符串

sizeof§, p 是一个指针变量,也就是地址,4/8 个字节

sizeof(p+1), p + 1 跳过一个元素,指向第二个元素,还是一个地址,4/8 个字节

sizeof(*p), *p 字符串首元素解引用,取出 a,a 是 char 类型,1 个字节

sizeof(p[0]), p[0] 取出字符‘a’,大小为 1 个字节

sizeof(&p), &p 取出的是 p 的地址,是一个二级指针,数据类型为 char** ,也就是 4/8 个字节

sizeof(&p+1), &p + 1,取出 p 的地址,是个二级指针,数据类型为 char** ,再跳过一个数组 ,还是一个地址, 4/8 个字节

sizeof(&p[0]+1), &p[0] 表明取出首元素的地址,跳过一个元素,指向第二个元素的地址,也就是 ‘b’ 的地址,还是一个地址,4/8 个字节

看一下运行结果:

代码六

#include <stdio.h>
#include <string.h>int main()
{char* p = "abcdef";printf("%d\n", strlen(p));printf("%d\n", strlen(p + 1));printf("%d\n", strlen(*p));printf("%d\n", strlen(p[0]));printf("%d\n", strlen(&p));printf("%d\n", strlen(&p + 1));printf("%d\n", strlen(&p[0] + 1));return 0;
}

strlen(p) 从第一个元素开始,到 \0 结束,就是6

strlen(p+1), 从第一个元素开始,+1 跳过一个元素,从第二个元素计算,也就是 5

strlen(*p), *p 取出第一个元素,不是地址,系统报错,硬要访问,a的ascll码值是97,访问的是地址编号为97,这是属于操作系统的是不允许访问的

strlen(p[0]), p[0] 取出第一个元素,不是地址,系统报错,硬要访问,a的ascll码值是97,访问的是地址编号为97,这是属于操作系统的是不允许访问的

strlen(&p), &p 指向 p 的地址,未知空间,不知道何时遇到 \0 , 随机值

strlen(&p+1), &p 取出 p 的地址, &p+1 跳过一个 char* , 未知空间,随机值

strlen(&p[0]+1), &p[0] 取出首元素的地址,+1 跳过一个元素,指向第二个元素,也就是 5

课外探讨:&p 和 &p + 1 有关系吗?实际没有,因为你不知道 p 内部是否有 \0 ,如果有,他们的大小就是差 1


二维数组

首先我们来回顾一下二维数组,二维数组可以看出一个个一维数组组成的,举个例子:
int arr [3][3] = {1,2,3,4,5,6,7,8,9};

我们可以将二位数组看成由一个又一个的一维数组组成,则二维数组的首元素地址就是第一行的地址。

arr [0], arr[1], arr[2], 如果单独放在sizeof 内部的话分别表示 数组的第一行 ,第二行,第三行的数组名,否则就是代表数组第一行、第二行、第三行的首元素地址。

我们来看一下下面的题目:

#include <stdio.h>
#include <string.h>int main()
{int a[3][4] = { 0 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(a[0][0]));printf("%d\n", sizeof(a[0]));printf("%d\n", sizeof(a[0] + 1));printf("%d\n", sizeof(*(a[0] + 1)));printf("%d\n", sizeof(a + 1));printf("%d\n", sizeof(*(a + 1)));printf("%d\n", sizeof(&a[0] + 1));printf("%d\n", sizeof(*(&a[0] + 1)));printf("%d\n", sizeof(*a));printf("%d\n", sizeof(a[3]));return 0;
}

sizeof(a), a 单独放在sizeof 内部, 表示整个数组的大小,3 * 4 * (sizeof(int)) = 48

sizeof(a[0][0]), a[0][0] 大小为 4 个字节

sizeof(a[0]), a[0] 单独放在 sizeof 内部,表示第一行的数组大小, 4 * 4 = 16

sizeof(a[0]+1), a[0] 不是单独放在 sizeof 内部,则表示的是第一行的首元素 ,也就是 &a[0][0] ,+1 跳过一个元素,指向 a[0][1] 的地址,4/8 个字节

sizeof(*(a[0]+1)) , a[0] + 1 == &a[0][1], 解引用之后就是a[0][1], 也就是 4 个字节

sizeof(a+1), a 再这里表示数组的首元素也就是第一行的地址,+1跳过一行,就是第二行的地址,地址就是 4/8 个字节

sizeof(*(a+1)), a+1 指向第二行的地址,解引用后就是取出第二行的数组,大小就是 4 * 4 =16

sizeof(&a[0]+1), &a[0] 取出第一行的地址,+ 1 表示跳过一行,指向第二行的地址,4/8 个字节

sizeof(*(&a[0]+1)) , 解引用取出第二行,也就是 4 * 4 = 16 个字节

sizeof(*a), a 表示数组首元素的地址(第一行的地址),解引用取出第一行,大小为 4 * 4 = 16

sizeof(a[3]), a[3] 大小为 4 * 4 = 16 个字节,为什么不会有越界的问题,因为 sizeof 不参与计算,a[3]无需真实存在,仅仅通过类型的推断就能算出长度,a[3] 表示第四行的数组名,单独放在 sizeof 内部,计算的是第四行的大小,4 * 4 = 16

我们来看一下运行结果:


指针运算笔试题解析

题目一

#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表示数组首元素的地址,+1 跳过一个元素,* (a+1) 就是 取出 第二个元素( 2 )
&a 表示取出整个数组的元素,+ 1 跳过一个数组, int* prt = (int*)(&a+1),将&a+1 原先的数据类型(int () [5]) 强制类型转化为 int ,ptr-1 要注意了是向后移动一个元素,为什么呢?因为 ptr 的类型是 int* , - 1 也就是向后移动 int,最终指向 5

来看一下运行结果:

题目二

//在X86环境下
//假设结构体的⼤⼩是20个字节
//程序输出的结构是啥?#include <stdio.h>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;
}

这里的0x1就是表示1


p的类型是 struct Test * ,+1表示跳过一个结构体,也就是地址+20,由于0x是16进制,所以20换成16 进制就是 0x14, 0x100000 + 0x14 = 0x100014

(unsigned long) p将 p 强制类型转换为 无符号的长整型,+1就是0x100001

(unsigned int*)p 将p 强制类型转换为 unsigned int*,+1跳过 unsigned int 的字节大小,也就是0x100000 + 0x4 = 0x100004

运行结果如下:

题目三

#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}

所以数组a[3][2]={1,3,5,0,0,0},p=a[0]表示数组第一行的地址,p[0]相当于a[0][0]也就是取出第一行的首元素,也就是 1

运行结果如下:

题目四

//假设环境是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;
}

int a[5][5],a 的类型是int()[5], 因为这是一个二维数组,二维数组的首元素是二维数组的第一行,所以a的类型是 int () [5]
int (p)[4],无需置疑,p的类型就是int ()[4]

那么&a[4][2]就无需多讲,p[4][2]其实就是*(*(p+4)+2), p+4表示跳过4个int [4],然后+2 表示跳过2个int ,指向图如下图所示。

然后我们要知道指针 - 指针代表就是两个指针之间的元素个数,所以&p[4][2]-&a[4][2] 之间有4个元素,由于是低地址减去高地址,所以是-4

%d打印有符号的整数,就是-4
%p打印的是地址,所以我们需要知道-4在内存中然后存储,那就要将-4的补码写出来(-4的原码是10000000000000000000000000000100,反码就是11111111111111111111111111111011,补码就是11111111111111111111111111111100)也由于是x86环境下,所以是32位的地址,于是将补码转换成16进制的数值(也就是FFFFFFFC)

运行结果:

题目五

#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表示取出整个数组的地址,+1跳过一个数组,然后强制类型转换为int*, 赋给ptr1
aa表示数组的首元素,+1跳过一个元素,然后强制类型转换为int*, 赋给ptr2

ptr-1 由于ptr 是int*类型,所以跳过一个int ,同理ptr2-1也是跳过一个int

运行结果:

题目六

#include <stdio.h>int main()
{char* a[] = { "work","at","alibaba" };char** pa = a;pa++;printf("%s\n", *pa);return 0;
}

a是个字符指针数组,存放的是work,at,alibaba的首元素的地址
pa = a意味着pa是a的首元素的地址,pa++跳过一个char*,也就是指向a 的第二个元素,*pa 取出a的第二个元素,也就是at的首元素的地址,所以打印at

运行结果:

题目七

#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;
}

我们先将图画出来:

在这里+的优先级最低

** ++ cpp ,cpp先++,指向c+2的地址,解引用取出c+2,再解引用取出POINT的地址,

*--*++cpp+3 

首先cpp在上面已经自增过一次,再++之后cpp就指向c+1的地址,解引用取出c+1,然后c+1再–,变成c,再解引用就会取出ENTER的地址,然后+3,跳过三个元素,也就是指向E的地址,打印出ER

现在cpp是指向cp第三个元素的地址!

cpp[-2]+3,我们先来解读cpp[-2],cpp[-2]表示(cpp-2),也就是取出c+3的地址,*cpp[-2]解引用取出FIRST的地址,+3跳过三个元素,也就是指向S的地址,打印出ST

cpp[-1][-1],我们来分解一下*( *( cpp-1 )-1 ),cpp-1指向cp第二个元素的地址,解引用取出c+2, c+2-1=c+1, 解引用一下就取出NEW的地址,最后cpp[-1][-1] + 1 之后就是指向E的地址,也就是打印出EW

运行结果:

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

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

相关文章

作业1-32 B3620 x 进制转 10 进制

题目 思路 分析题目可知&#xff0c;此题可以用到大写字母&#xff0c;也就是从A开始&#xff0c;分别表示11往后的数字。 那么就用一个for循环&#xff0c;将零到九划分为一个等级&#xff0c;将A到Z划分为一个等级。 for(int i0;i<str.length();i){if(str[i]>0&&…

Zabbix(四)

Zabbix Proxy zabbix作为一个分布式监控系统(分布式监控解决方案)&#xff0c;支持通过代理(proxy)收集zabbix agent的监控数据&#xff0c;然后由zabbix proxy再把数据发送给zabbix server&#xff0c;也就是zabbix proxy 可以代替zabbix server收集监控数据&#xff0c;然后…

【免费资源】Unity真实广阔的沙漠场景等你来解锁!

Unity真实广阔的沙漠场景等你来解锁&#xff01; Unity 每周免费资源上新啦&#xff01;此次更新的是广阔的沙漠场景&#xff0c;其中包含 14 个预制体&#xff0c;每个预制体都包含 LOD、400-2000 顶点和 4K 纹理。现在&#xff0c;只需登录 Asset Store&#xff0c;即可免费领…

怎么将pom在文件放到src下方

今天在IDEA从git拉取项目的时候&#xff0c;发现pom.xml文件在文件夹src的上方&#xff0c;平时看惯了项目的pom.xml文件在文件夹src的下方&#xff0c;应该怎么去设置呢&#xff1f; 点击设置——>点击Folder Always on Top 即可 参考&#xff1a;http://t.csdnimg.cn/s34…

达梦数据库——如何查看数据库大字段中的数据内容

今天get到一个小知识点 分享给大家&#xff0c;如何在数据库查看大字段中的数据内容。 以下为演示步骤&#xff0c;简单易懂&#xff0c;操练起来吧 首先创建一个含有CLOB、TEXT的大字段测试表 create table "SYSDBA"."CS"("COLUMN_1" CLOB,&qu…

配电网数字化转型全面推进:《关于新形势下配电网高质量发展的指导意见》

近日&#xff0c;国家发展改革委、国家能源局印发了《关于新形势下配电网高质量发展的指导意见》&#xff08;以下简称《意见》&#xff09;&#xff0c;到2030年&#xff0c;基本完成配电网柔性化、智能化、数字化转型&#xff0c;实现主配微网多级协同、海量资源聚合互动、多…

【Linux】第四十站:线程概念

文章目录 一、线程二、Linux中线程应该如何理解三、重新定义线程四、四谈进程地址空间&#xff08;页表相关&#xff09;五、Linux线程周边的概念1. 线程与进程切换2.线程优点3.线程缺点4.线程异常5.线程用途 一、线程 线程&#xff1a;是进程内的一个执行分支。线程的执行粒度…

Linux mmap系统调用

文章目录 前言一、mmap()函数简介二、代码演示2.1 mmap使用场景2.2 私有匿名映射2.3 私有文件映射2.4 共享匿名映射2.5 共享文件映射 参考 前言 NAMEmmap, munmap - map or unmap files or devices into memorySYNOPSIS#include <sys/mman.h>void *mmap(void *addr, siz…

跨境电商趋势解析:社交电商携手私域流量运营,精准触达与转化

随着全球化的深入发展&#xff0c;跨境电商逐渐成为全球贸易的重要组成部分。在这一背景下&#xff0c;社交电商作为一种新兴的商业模式&#xff0c;正逐渐在跨境电商领域崭露头角&#xff0c;并对私域流量的运营产生了深远的影响。本文Nox聚星将和大家分析社交电商在跨境电商中…

浏览器一键重新发起请求

一、需求场景 在前端开发过程中&#xff0c;经常会需要重新请求后台进行代码调试&#xff0c;之前的常规方法是刷新浏览器页面或者点击页面进行交互&#xff0c;这样对多个请求的场景就很方便&#xff0c;但是往往很多时候我们只是单纯的想重新发起一个请求&#xff08;多个请求…

力扣---接雨水---单调队列

题目&#xff1a; 单调队列思想&#xff1a; 没有思路的小伙伴可以先把这个想清楚哦&#xff1a;力扣hot10---大根堆双端队列-CSDN博客 从上面的图就可以发现&#xff0c;如果柱子呈递减序列&#xff0c;那么不会接到雨水&#xff0c;只要有一个小凸起柱子&#xff0c;那么这个…

PubMedQA数据集分享

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2024-2-28 该数据集由匹兹堡、卡内基梅隆等大学提出&#xff0c;它是第一个需要对生物医学研究文本进行推理&#xff0c;特别是其定量内容的问答数据集。…

【前端】-初始前端以及html的学习

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …

Vue开发实例(八)Vuex状态管理store

Vuex状态管理store 一、Vuex的安装与配置二、store使用方法1、基础使用2、提交变更3、getters使用4、在其他页面&#xff08;组件&#xff09;中显示5、modules多模块 做vue项目的时候&#xff0c; store状态管理器可以帮助我们完成一些数据的存储和管理&#xff0c;通俗理解是…

如何将任何文本转换为概念图(GC)

原文地址&#xff1a;how-to-convert-any-text-into-a-graph-of-concepts 使用 Mistral 7B 将任何文本语料库转换为知识图的方法 2023 年 11 月 10 日 使用递归 RAG 方法来实现具有多跳推理的 QnA&#xff0c;以回答基于大型文本语料库的复杂查询。 知识图增强生成与递归 R…

unity-urp:视野雾

问题背景 恐怖游戏在黑夜或者某些场景下&#xff0c;需要用雾或者黑暗遮盖视野&#xff0c;搭建游戏氛围 效果 场景中&#xff0c;雾会遮挡场景和怪物&#xff0c;但是在玩家视野内雾会消散&#xff0c;距离玩家越近雾越薄。 当前是第三人称视角&#xff0c;但是可以轻松的…

【C++】十大排序算法之 归并排序 快速排序

本次介绍内容参考自&#xff1a;十大经典排序算法&#xff08;C实现&#xff09; - fengMisaka - 博客园 (cnblogs.com) 排序算法是《数据结构与算法》中最基本的算法之一。 十种常见排序算法可以分为两大类&#xff1a; 比较类排序&#xff1a;通过比较来决定元素间的相对次序…

力扣--滑动窗口438.找到字符串中所有字母异位词

思路分析&#xff1a; 使用两个数组snum和pnum分别记录字符串s和p中各字符出现的次数。遍历字符串p&#xff0c;统计其中各字符的出现次数&#xff0c;存储在pnum数组中。初始化snum数组&#xff0c;统计s的前m-1个字符的出现次数。从第m个字符开始遍历s&#xff0c;通过滑动窗…

史上最细,接口自动化测试用例设计编写总结,一篇带你打通...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 说到自动化测试&a…

亚信安慧AntDB:“融合+实时”引领数据库创新

在当今多变的数据应用场景中&#xff0c;AntDB作为行业领先的超融合流式实时数仓&#xff0c;秉承着“融合实时”的研发理念&#xff0c;全面应对企业日益复杂的数据处理需求。通过SQL接口访问多种执行引擎&#xff0c;AntDB在实现交易、分析等多重能力的“超融合”方面取得了显…