22.一节课讲明白c语言指针(上)
hello,小伙伴们,大家好,这里是左左右,这期视频给 大家讲解一下c语言中的指针,学过c语言的小伙伴们都知 道,指针算是c语言中的拦路虎了,很多人学到这里就开始 犯糊涂了,之前视频中我们讲过内存的最小单位是比特 (Bit),8个bit组成一个字节,那么cpu是怎么在庞大的 内存中找到我们存入的数据呢?
其实每个字节都有它的地址,cpu就是通过地址找到我们存进去的值的,这就像你点外卖,外卖员是通过你填写的地址来找到你是一个道理的,而接下来要讲的指针,它里面存放的就是地址,打开vscode来试一下,首先定义一个int类型的变量a,将十六进制的数12345678赋值给变量a,接着定义一个指向int类型的指针p1,这里的int * 它是一个整体,* 代表指针,int代表我们定义的指针是指向int型的数据类型的,接着我们把a的地址取出来存放到定义好的指针p1中,这里取地址我们用“与”(&)这个符号,这行代码的意思就是将变量a的地址取出来放到指针p1中。
#include<stdio.h>
int main()
{
int a = 0x12345678;
int *p1;
p1 = &a;
return 0;
}
刚才我们讲过内存每个字节都是有对应的地址的,这个地址在内存中是独一无二的,内存本来就是存放数据的容器,这里你可以这样理解,内存中的字节相当于是杯子,而每个杯子外面都印有编码,这个编码就是地址,这里我们定义了int类型的变量a,由于int是四个字节的,相当于内存给了你四个杯子,至于杯子里要放什么那是你的事,你可以放水或牛奶又或者是咖啡或饮料,内存将来可以通过杯子外面的印的编码就知道杯子里装的是什么了。
接下来我们通过a的地址找到存在里面的值并打印出来,到这里大家是不是已经开始糊涂了,其实这里的 * 是取内容的意思,就是把存放在指针p1对应地址中的值给取出来,因为p1里存放的是a的地址,所以点击运行,这里就输出16进制的12345678。
#include<stdio.h>
int main()
{
int a = 0x12345678;
int *p1;
p1 = &a;
printf("%x\n",*p1);
return 0;
}
这种类似的我们之前数组那期视频是遇到过的,比如我们定义一个数组,当前面有数据类型时,方括号里的值就代表定义数组的成员个数,而前面没有数据类型时,方括号里的值就代表数组的成员序号,而*前有数据类型就是定义指针,*前没有数据类型就是取出指针对应地址的值.
#include<stdio.h>
int main()
{
int a = 0x12345678;
int *p1;
p1 = &a;
printf("%x\n",*p1);
int arr[] = {1,2,3};
arr[0];
return 0;
}
用相同的方法来定义一个char类型的变量,同时我们把指针中的值和占用多少内存打印出来看一下,这里的结果都是8,就是说不管你定义的是int还是char的指针,指针占用的内存空间都是8个字节的,因为指针是用来存放地址的,说明地址是8个字节的。
#include<stdio.h>
int main()
{
int a = 0x12345678;
int *p1;
p1 = &a;
printf("%x\n",*p1);
printf("%x\n",p1);
printf("%zu\n",sizeof(p1));
char b = 'c';
char *p2;
p2 = &b;
printf("%c\n",*p2);
printf("%x\n",p2);
printf("%zu\n",sizeof(p2));
return 0;
}
那为什么地址是8个字节的呢?因为我的电脑是64位的,这里的位指的是比特(bit),也就是8字节,同理,如果你的电脑是32位的,地址大小就是4个字节的,接着详细讲解一下每行代码的执行过程过程。
前面我们一直在强调,定义数据类型就是向内存要空间的过程,这里我们定义了int a ,系统就分配给我们4个字节的空间,并将16进制的12345678放到系统给我们分配的空间中去,接着定义指针p1,系统给我们分配8个字节的空间,接着看下一行代码,前面我们讲过内存中的每个字节都有其对应的地址,int数据类型是4个字节的,也就是有4个地址,而指针只能存储一个地址,所以指针p1里存储的是int a的第一个地址,也就是首地址,这里有一个要点,大家一定要明白,地址是内存中字节的编号,它是一直存在的,就像刻在内存中一样,他不会因为指针的存在而存在,也不会因为指针的消失而消失,而我们定义指针只不过是把拿到的地址存在这个指针里而已,这就像你家的地址是真是存在的,而外卖员只不过是把你的地址存在他手机里是一个道理,就像水杯外印的编号,不会因为你把水喝掉而消失,这里你可以把指针理解为一种特殊的数据类型,它是专门用来存储地址的,指针的其他功能我会接着讲的,这行代码就是将p1对应地址中的值取出来,刚才我们讲过指针存放的是首地址,而int a是四个字节的,它是跨越4个地址的,指针是怎么将四个地址中的值同时取出来的呢,这时我们定义指针时前面的int就起到关键作用了,这里的int就是告诉指针在取值时要从四个相邻地址去取值,这里只是我自己的个人想法,我们来验证一下这个想法。
我们将这里的int改为char,我们都知道char类型是一个字节的,我们来输出看一下,这里虽然报错,但它还是输出了78,因为我们前面定义指针时,用的是char这个数据类型,就是说这时的指针认为它取一个字节地址中的内容就可以了,接着把char改为short,short是两个字节的,这是我们打印输出看一下,这个结果是我们意料之中的对不对,这时的指针认为它把和首地址相邻的一个地址的内容取出来就可以了,只有我们理解到这一步,你才能彻底理解为什么要这样定义指针,要不然你总是糊里糊涂的。
int main()
{
int a = 0x12345678;
short *p1;
p1 = &a;
printf("%x\n",*p1);
printf("%x\n",p1);
printf("%zu\n",sizeof(p1));
// char b = 'c';
// char *p2;
// p2 = &b;
// printf("%c\n",*p2);
// printf("%x\n",p2);
// printf("%zu\n",sizeof(p2));
return 0;
}
我将这节课的主要内容总结到这里,大家一定要去记,去理解,这期视频对以后指针的学习至关重要,由于指针内容比较多,我会分三到四期给大家讲解,好的,今天的视频就到这里了,您的关注,点赞和收藏是我持续更新下去的最大动力,我们下期见。