24.一节课讲明白c语言指针(中②)
hello,小伙伴们,大家好,这里是左左右,这期视频接着给大家讲C语言基础中指针这一部分,讲这期视频前先问大家这样一个问题,指针和数组名是否等价?这时好多小伙伴们就要说了,数组名就是指针,我们老师就是这样讲的,也一直这样用的,肯定没有问题,但是如果听过上期视频的小伙们就知道,数组名就是指针这样的说法是不准确的,那么数组名和指针之间到底有什么关系呢?通过这期视频就让大家彻底弄明白,首先打开vscode的来写这样一段代码,这里%p就是专门来输出指针地址的,调试输出来看一下,这里虽然报错了,但可以看到三个输出的结果是一模一样的,看到这里,对于刚学习C语言或者C语言基础比较薄弱的小伙伴们来说,是不是心态都崩了?对于听过我前两期视频的小伙伴们很容易判断出这里第一个和第三个是等效的,他们都是指向数组中第一个元素的首地址的,那么给数组名取地址为什么输出的也是这个地址值呢?他们三个是不是等效的?
#include<stdio.h>
int main()
{
short arr[] = {0x1234,0x5678,0x1234};
short *p1 = arr;
short *p2 = &arr;
short *p3 = &arr[0];
printf("%p\n%p\n%p\n",p1,p2,p3);
return 0;
}
带着这个疑问我们再来写这样一段代码,调试输出来看一下,这里的指针变量p1和p2是我们熟悉的,这里的p3代表什么什么呢?而且它也报错了。
#include<stdio.h>
int main()
{
int a = 0x12345678;
char b = '1';
short arr[] = {0x1234,0x5678,0x1234};
int *p1 = &a;
char *p2 = &b;
short *p3 = &arr;
printf("%p\n%p\n%p\n",p1,p2,p3);
return 0;
}
接下来我们详细分析一下这段代码,首先我们定义int类型变量a,并赋值,同理定义char类型变量b,并赋值,定义short类型的数组,并赋值,接着定义指针变量p1,通过取地址符(&)把int a的首地址存入指针p1中,而且指针p1是指向整个变量a占用的内存空间的。
同理定义指针变量p2,这时的指针p2存放的就是char b的首地址,而且指针p2是指向整个变量b占用的内存空间的。
同理定义指针变量p3,这时的指针p3存放的就是arr的首地址,而且指针p3是指向整个数组arr占用的内存空间的。
这时我们返回来看这里定义指针变量p3时,用的是short *,它是指向短整型(short)的指针和前面定义的int *一样,它不能代表指向数组的指针,那我们应该如何定义指向数组的指针呢?,这时我们就要引出一个专业名词了 它就是数组指针,也就是指向数组的指针,他的固定写法是这样的(数据类型 (*指针变量名)[数组长度];),所以照猫画虎 这里的指针p3要这样定义,点击运行,是不是就没有报错了。

#include<stdio.h>
int main()
{
int a = 0x12345678;
char b = '1';
short arr[] = {0x1234,0x5678,0x1234};
int *p1 = &a;
char *p2 = &b;
short (*p3)[3] = &arr;
printf("%p\n%p\n%p\n",p1,p2,p3);
return 0;
}
接着回到我们刚开始写的第一段代码,按照数组指针的写法把p2改一下,点击运行,是不是就没有报错了。
#include<stdio.h>
int main()
{
short arr[] = {0x1234,0x5678,0x1234};
short *p1 = arr;
short (*p2)[3] = &arr;
short *p3 = &arr[0];
printf("%p\n%p\n%p\n",p1,p2,p3);
return 0;
}
通过这部分内容的学习,我们是不是发现这时的数组名arr和变量名a,和b都是一样的?数组名只不过是数组的标识符而已,只不过C语言赋予数组名一部分指针的功能而已,这个也从另一个方向验证了数组名并不等于指针,结合前两期视频我们得出这样一个结论,当给数组名取地址时 它存放的是数组的首地址,它指向的是整个数组。
当把数组名单独拿出来时,它存放的是数组中第一个元素的首地址,它指向的是数组中的第一个元素,它与数组首元素取地址等效,所以他两输出的结果虽然相同,但指向是大不相同的。
接着我们写这样一段代码,这样写是不是看起来有点太啰嗦了?那有没有更高效的写法呢?答案肯定是有的,我们可以将所有指针放到一个数组,如果我们这样来定义就与普通数组的定义方法一样了,无法作区分了,所以要在int后面加个*号,代表我们定义数组成员是指针类型的,我们将这样的数组称之为指针数组,我们要能把前面讲的数组指针区分出来,其中数组指针的重点是指针二字,他代表指向数组的指针,而指针数组的重点是数组二字,他代表由指针组成的数组。
#include<stdio.h>
int main()
{
int a = 1;
int b = 1;
int c = 1;
int d = 1;
int *p1 = &a;
int *p2 = &b;
int *p3 = &c;
int *p4 = &d;
printf("%p\n%p\n%p\n",p1,p2,p3);
int* p[] = {&a,&b,&c,&d};
printf("%p\n%p\n%p\n",p[0],p[1],p[2],p[3]);
return 0;
}
讲到这里我将数组名和指针的区别与联系,总结了一张表格在这里供大家参考,其中我把这一排单独拿出来给大家讲一下。
我们写这样一段大家熟悉的代码,点击运行,没有任何问题,这时我们将指针p+1改为p++,点击运行,也没有问题,但当我们将数组名arr+1改为arr++,点击运行,就报错了,说明在C语言中数组名++ 的写法是不合法的,大家不要这样写。
#include<stdio.h>
int main()
{
short arr[] = {0x1234,0x5678,0x1234};
short *p = arr;
printf("%x\n",arr);
printf("%x\n",arr++);
printf("%x\n",p);
printf("%x\n",p++);
return 0;
}
总结这个表格的目的就是为了大家在以后遇到数组名和指针的相关问题解决不了时,返回来看一下,找找灵感,还有这里最后一行,知识点比较多,我们将在下期视频给大家展开来讲解,老样子,习题时间,当我把这里的注释取消时,输出的结果是什么?大家可以通过弹幕的方式把答案发出来,同时我也会将答案放到评论区,这期视频如果听不懂的小伙伴们可以先前面两期视频听一遍,好的,今天的视频就到这里了,您的关注,点赞和收藏是我持续更新下去的最大动力,我们下期见。