23.一节课讲明白c语言指针(中①)
hello,小伙伴们,大家好,这里是左左右,这期视频给大家讲解一下c语言中的指针和数组,大家首先来思考这样一个问题,如何通过指针来分别输出数组中的各个元素,我来给大家写一下,看和你想的一样不,首先打开vscode来定义一个short类型的数组,接着定义指针变量p1,然后把arr数组中第一个元素的首地址取出来,这时我们取指针变量p1中的内容就得到数组中第一个元素的值,同时将指针变量p1内存储的地址和占用内存大小分别打印出来,同理,我们将数组中剩下的元素也都打印出来。
#include<stdio.h>
int main()
{
short arr[] = {0x1234,0x5678,0x1234};
short *p1;
p1 = &(arr[0]);
printf("%x,%x,%zu\n",*p1,p1,sizeof(p1));
short *p2;
p2 = &(arr[1]);
printf("%x,%x,%zu\n",*p2,p2,sizeof(p2));
short *p3;
p3 = &(arr[2]);
printf("%x,%x,%zu\n",*p3,p3,sizeof(p3));
return 0;
}
点击运行,打印输出是不是没有问题。
回过头来,将每行代码仔细分析一下,首先来看第一行代码,由于数据类型short是两个字节的,这里我们定义的数组成员数是3个,所以内存给我们分配了6个字节的空间,同时把值放入到内存中,接着下一行代码我们定义了指针p1,向内存要了8个字节的空间用来存放地址,紧接着将arr数组中第一个元素的首地址存入p1,这时打印输出的第一个值就是指针p1中对应地址的值,指针说白了就是通过庙来找和尚,第二个值是指针变量p1里存放的地址,第三个是指针占用内存的大小,也就是8个字节,同理,p2,p3都是一样的,在这里就不赘述了。
那么这里有没有简单的写法呢?答案肯定是有的,我们一般也不这样写,前面这样写是方便大家理解,这里一长串可以用数组名直接来代替,打印输出来看一下,是不是也没有问题?,写到这里很多老师会说因为p1是指针,p1等于arr,所以数组名也是指针,在这里你可以把它理解为指针,但这样的说法是不准确的,这个很好推翻的,我们把arr用sizeof打印出来,如果arr是指针,这里打印输出应该是8才对,但这里输出的并不是指针的大小,而是数组的大小,short的数据类型是2个字节的,成员数是3,所以输出结果是6。
#include<stdio.h>
int main()
{
short arr[] = {0x1234,0x5678,0x1234};
short *p1;
p1 = arr;
// printf("%zu\n",sizeof(arr));
printf("%x,%x,%zu\n",*p1,p1,sizeof(p1));
short *p2;
p2 = arr+1;
printf("%x,%x,%zu\n",*p2,p2,sizeof(p2));
short *p3;
p3 = arr+2;
printf("%x,%x,%zu\n",*p3,p3,sizeof(p3));
return 0;
}
通过这里我们发现指针是可以执行加减运算的,同时也得出指针的另一个功能,就是跳转功能,当arr+1时,指针跳转到数组第二个成员的首地址,同理,当arr+2时,指针跳转到数组第三个成员的首地址,这里的加1、加2其实代表的是指针跳转的步数,加1代表跳转1步,加2代表跳转两步,这里指针每次跳转是跳转了2个字节,为什么不是1个字节呢,这是因为我们定义数组时前面数据类型是short,而short就是两个字节的,我们把指针每次跳转的字节数称之为步幅,定义数组时前面的数据就决定了步幅的大小。
我们来验证一下,将定义数组时前面的short改为int,调试输出可以看出,每次指针跳转的步幅就变成4了。
#include<stdio.h>
int main()
{
int arr[] = {0x1234,0x5678,0x1234};
short *p1;
p1 = arr;
// printf("%zu\n",sizeof(arr));
printf("%x,%x,%zu\n",*p1,p1,sizeof(p1));
short *p2;
p2 = arr+1;
printf("%x,%x,%zu\n",*p2,p2,sizeof(p2));
short *p3;
p3 = arr+2;
printf("%x,%x,%zu\n",*p3,p3,sizeof(p3));
return 0;
}
学到这里就可以总结出指针的3大功能了,一、指针是一种特殊的变量,它是用来存放首地址的,二、指针具有指向内存空间功能,指向内存的大小是由定义指针时前面的数据类型决定的,三、指针具有跳转功能,跳转步数是由指针执行加减运算时的值决定的,步幅是由定义数组时的数据类型决定的。
这里我们还可以用for循环将数组成员遍历出来,这里的数组成员数我们可以通过 ,数组占用空间的大小除以成员占用空间的大小来算出来,调试输出来看一下,是不是和之前一样?,这里也可以得出这样一个结论,arr和arr[0]等效,(arr+1)和arr[1]等效,*(arr+2)和arr[2]等效。
#include<stdio.h>
int main()
{
short arr[] = {0x1234,0x5678,0x1234};
for(int i = 0;i < (sizeof(arr)/sizeof(short));i++)
{
printf("%x,%x,%x\n",*(arr+i),arr[i],arr+i);
}
return 0;
}
接下来,出一道思考题,这里的打印输出的值等于多少,大家可以通过弹幕的方式把答案发出来。
答案:2
因为:&(arr【2】) = arr + 2;&(arr【0】) = arr;
所以:&(arr【2】) - &(arr【0】) = 2;
这期视频如果听不懂的小伙伴们可以先把上期视频听一遍,下期视频会更新指针与数组名的区别与联系,好的,今天的视频就到这里了,您的关注,点赞和收藏是我持续更新下去的最大动力,我们下期见。