目录
内存和地址
指针变量和地址关系
1.内存和地址
1.1 内存的概念
我们知道CPU在处理数据的时候,需要的数据是从内存中读取的,处理后的数据也会放回内存中。
例如我们购买的手机,有8G/16G的运行内存,那么这些运行内存是如何实现管理的呢?
那么首先,我们把内存划分为一个个的内存单元,每个单元可以用来存放一个字节,而一个字节有包括8个比特位。
那么我们简单的罗列一下数据的换算关系:
1BITE=8BIT
1KB=1024BYTE
1MB=1024KB
1G=1024MB
1TB=1024GB
1PB=1024TB
因此当手机运行起来需要进行数据处理的时候,那么就会工内存单元里面去查询这个内存单元。
那么计算机内存里面,其实就将内存进行了管理,也就是将内存单元一个个进行编号,因此CPU想要查询这里面的内存空间,就可以通过这些内存单元去访问。
在计算机中,我们把内存单元的编号叫做地址,而在C语言中给地址起了名字叫做“指针”
因此我们也不防这么理解:
每一块内存单元的编号==地址==指针
以下是内存的一个存放的一个个的内存单元
1.2 为什么要给内存编址
大家来看一下以下这一张图,可以知道CPU与内存之间的交互,是通过数据总线,地址总线和控制总线。
那么32位机就有32根地址总线,而每根线有两种状态0/1,而32根总线就有2^32个地址
例如,如果地址线是2根,那么通过组合0/1则有四个地址,因此一次类推,32根总线就有2^32个地址,64根总线就有2^64个地址。
因此,在计算机的内部,只要发送命令就可以操作对应的内存单元,并找到对应地址上的数据,并通过数据总线传入到CPU内寄存器。
2.指针变量和地址关系
2.1取地址操作符 &
当我们编写代码的时候,创建一个变量的本质就是向内存申请一块空间。
可以使用F10或者windows按下Fn+F10,进入逐过程debug
好了,我们打开监视窗口,并输入&a可以查看到存放a的地址,也就是编译器给a分配的地址。
变量创建的本质是在内存上开辟空间。
为了方便调试,我们可以在内层上观察存放的地址,将自动这里改成1来观察内存
在地址输入&a就可以看到地址的内容:可以看到内存中的地址是0x00eff8dc ,存放的数据是0a,这里为什么是0a呢,是将10转为16进制,所以是0a。
转换过程,我们是先将10进制转为二进制,,然后再通过二级制转为16进制。
0000 0000 0000 0000 0000 0000 0000 1010
0x 00 00 00 0a
0a就是一个字节对应一个地址
名称 | 值 | 类型 | |
---|---|---|---|
▶ | &a | 0x00eff8dc {10} | int * |
当然,我们也可以将&a打印出来看一下:
这里你会注意到每一次打印的地址不一样,是因为内存每一次分配的地址不是同一个地址。
如果自动这里观察是4,代表观察的是四个字节,那么0a则是属于较小字节的地址。
#include <stdio.h>
int main()
{
int a = 10; //变量创建的本质,在内层上开辟空间
//要向内存申请4个字节的空间,存放数据10
printf("%p\n", &a);
//对于a来说,我们拿到的是a所占4个字节的第一个字节的地址,也就是字节较小的那个字节的地址
//我们只需要拿到其存放的字节地址即可,这个地址是一个16进制的数值
return 0;
}
2.2 指针变量
2.2.1 我们要认识一下,什么是指针变量。
定义一个指针变量
int * ptr = &a; //ptr的类型是int * ,*是在说明ptr是指针变量,ptr指向的对象是int类型
这个ptr就叫做指针变量,用来存放指针的变量就叫做指针变量。
通俗一点理解:存放在指针变量中的值都会被认为是地址。
int * 写在ptr的左边,*说明ptr是指针变量,而int则是说明ptr指向的 整型(int)类型的对象
拓展char * ptr,*说明ptr是指针变量,而char则是说明ptr指向的 字符型(char)类型的对象
#include <stdio.h>
int main()
{
int a = 10;
printf("%p\n", &a);
//创建一个变量可以用来存放这个地址
int* ptr = &a; // ptr叫做指针变量,存放指针的变量,所以叫做指针变量。
return 0;
}
#include <stdio.h>
int main()
{
double a;
char* ptr = &a;
printf("%c\n", a);
return 0;
}
总结:指针变量就算用来存放地址的
存放在指针变量中的值,都会被当成地址使用。
2.2.2 解引用操作符
* 是解引用操作符,或者是间接操作符
那么在C语言中,我们可以通过指针找到地址指向的对象。
这时候就会引入一个操作符,解引用操作符 *
*ptr 通过ptr中存放的地址,找到指向的空间,*ptr相当于就算a变量的数值20
#include <stdio.h>
int main()
{
int a = 20;
int* ptr = &a;
*ptr = 10; //*解引用操作符/间接访问操作符
//*ptr的意思就算通过ptr中存放的地址,找到地址指向的空间,*ptr就是a
printf("%d\n",a);
return 0;
}
当*ptr=10,相当于改变存放在地址中的a的值,我们打印看一下结果输出a=10,说明*ptr是通过ptr存放的地址,找到指向的空间,并将该值进行修改。通俗点来说就算a中不方便修改的值,可以让ptr来改。
2.3 指针变量的大小
在32位机中指针变量占用四个字节,64位机中指针变量占用8个字节。
我们打印看一下,X86环境下,非指针不同类型占用了几个字节
#include <stdio.h>
int main()
{
printf("%d\n",sizeof(char));
printf("%d\n",sizeof(short));
printf("%d\n",sizeof(int));
printf("%d\n",sizeof(double));
}
X86环境下,如果是指针不同类型占用了4个字节
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char *));
printf("%d\n", sizeof(short *));
printf("%d\n", sizeof(int *));
printf("%d\n", sizeof(double *));
}
X64环境下,如果是指针不同类型占用了8个字节
2.4 总结:
32个位地址下,32个bit位,指针变量大小是4个字节
64个位地址下,64个bit位,指针变量大小是8个字节
指针变量的大小跟类型没有关系,只要是指针类型的变量,在相同的平台,如32位,64位下是相同的。
最后,请各位发财的金手指,帮忙点点赞和关注!
💁♂️💁♀️🙋🙋♂️🙋♀️🧏🧏♂️一赞三连🧏♀️🙇🙇♂️🙇♀️🤦🤦♂️🤦♀️🤷🤷♂️🤷♀️
💁♂️💁♀️🙋🙋♂️🙋♀️🧏🧏♂️一赞三连🧏♀️🙇🙇♂️🙇♀️🤦🤦♂️🤦♀️🤷🤷♂️🤷♀️
💁♂️💁♀️🙋🙋♂️🙋♀️🧏🧏♂️一赞三连🧏♀️🙇🙇♂️🙇♀️🤦🤦♂️🤦♀️🤷🤷♂️🤷♀️