编辑
巅峰诞生虚伪的拥护,黄昏见证忠诚的信徒,心立的不是冠军,而是不屈服命运的布朗克斯,曙光会再次回来🥊🥊🥊
目录
1、内存布局是什么
在学习指针之前,我们应该先了解到内存原理。内存是计算机非常重要的存储器,我们所有正在运行的程序都是在内存中进行的,内存就像我们人类的大脑一样想什么做什么都用它。那么在计算机中我们为了有效的使用内存,我们就把内存分为一个个的单元,方便我们去使用。这个单元我们定义大小为1字节,当然为了精准的访问这些单元,我们都会给它分配独立的编号,这些编号我们称为内存地址。
编辑
可能有人会问,这些内存地址有什么用呢?这些地址就是给指针指明了方面,我们通过指针就可以找到这个地址所存的内容,然后可以对这个地址的内容进行操作。所以我们可以说指针就是地址。
1.1、指针占多少内存
指针在内存中占几个字节呢?它在32位操作系统下占4个字节,在64位操作系统下占 8个字节。我们还是用sizeof操作符来取字节数。
🤼♀️下图32位:
编辑
🤼下图64位 :
编辑
sizeof是C语言的内置运算符,已字节为单位给出指定类型的大小。C99和C11提供%zd转换说明匹配sizeof的返回类型(即,size_t类型)。一些不支持C99和C11的编译器可用%u和%lu代替%zd。这里在我们知道64位下就用%zd来得到占字节数就行了。
1.2、系统位是按照多少进制存放的
知道了指针在32位和64位系统下占多少个字节后,我们来了解一下32位系统的存储原理,在我的上篇文章中我提到过0x开头的是16进制。下面我来解释为啥要用16进制表示位数。首先我们计算机分为16位、32位、64位不等。就拿32位来解释,存储器是按照二进制来存储的。因此我们32位内存占用的空间是2^32,也就是4,294,967,296。那么如果就把0到4,294,967,296没有条理的扔在内存里面,我相信程序是不可能运行出来的。因此我们把这些数按照顺序依次排放在内存里面,以0到2^32排放在内存里面。也就是32个0到32个1。
🤼下面我们来看一个图来理解:
编辑
可见上图中我们从低到高依次往上增加,这样就非常的有条理。相信内存在运转的时候一定可以按照顺序找到该地址。
但是,我们按照32为二进制形式代表一个地址编号的话那就太长了 ,所以我们把32位比特位转换为16进制。这样的话,32位就变成8位十六进制。
🤼♀️如下图所示:
编辑
可能有些人就问到了一个字节最大对应的十六进制也是0xFF啊,上图中的0xFFFFFFFF为什么也占一个字节呢?0xFFFFFFFF只是一个地址编号,这个地址编号所占的内存为一个字节。
编辑
我们为什么要用0x(十六进制)来表示一个存储空间,相信大家已经一目了然了。由于用二进制形式表示太长了,我们用十六进制来表示缩短了许多。
2、指针是什么
1. 指针是内存中一个最小单元的编号,也就是地址
2. 平时口语中说的指针,通常指的是指针变量,是用来存放内存地址的变量
在生活中我们认为指针无非是一个物体指向另一个物体的指针
编辑
在C语言中,我们认为指针就是地址。指针变量是用来存储变量的内存地址,就像常量与变量一样他们都在内存有一块地址。而且指针变量同常量与变量一样需要对其声明。如 int* p;
int* p /*一个整形指针变量p*/
char* p /*一个字符型指针变量p*/
double* p /*一个双精度浮点型指针变量p*/
float* p /*一个单精度浮点型指针变量p*/
2.1、怎样定义一个指针
定义一个指针,跟定义一个常量是有非常大的不同的。我们定义一个常量是直接类型+变量名=变量。而指针我们是类型*+变量名1=&变量名2。
格式为:数据类型*+变量名1=&变量2,如定义一个指针变量p=a的地址:int* p=&a;
🤼♀️我们来看代码:
#include <stdio.h> int main() { int a = 10; // 定义一个整形变量a=10 int* p = &a; // 定义一个整形指针变量p=a的地址 return 0; }
- 上图代码中,*号就是我们指针的一个表示,&号我们叫取地址操作符。
- 在一个变量前加*号则这个变量就成为指针变量如:变量p变为整形指针变量int* p
- 在一个变量前加&号则表面这个变量的地址如:变量a的地址&a
我们可以通过%p格式符输出变量的地址,下程序中因为指针变量已经指向a的地址了,所以我们直接认为p的地址等同于a的地址。
#include <stdio.h> int main() { int a = 10; // 定义一个整形变量a=10 int* p = &a; // 定义一个整形指针变量p=a的地址 printf("a变量的地址:%p\n",p);//输出变量a的地址 return 0; }
结果 :a变量的地址:0x12FFAB0
编辑
这里原本指针变量p的地址也随机从内存中取的一块地址,只不过因为指向了a的地址。可以说指针变量的地址等同于变量a的地址了,这样我们就可以通过指针变量的地址改变 变量a地址里面的内容。
2.2、如何取出指针指向的地址?
#include <stdio.h> int main() { int a = 10; // 定义一个整形变量a=10 int* p = &a; // 定义一个整形指针变量p=a的地址 printf("a变量的地址:%p\n",p); return 0; }
结果 :a变量的地址:0x12FFAB0
编辑
那么怎样取出这个指针变量指向的a的地址呢?打开VS2019
步骤一
编辑
按F10,当VS底部出现就绪,说明你可以开始调试了。
步骤二
编辑
调试->窗口->内存->内存1,当然最后一步中的四个内存任意选择一个即可。
步骤三编辑
当左侧出现箭头说明程序可以开始调试了
步骤四
编辑
注意,a的地址是随机在内存中获取的。同样取一个a的地址,也许刚刚取的是0x012FFAB0。关闭调试后再打开调试获取a的地址就是0x011FFB90了。这里强调的是地址是随机获取的。
2.3、指针的解引用操作
上面,我介绍了如何定义一个指针变量并指向一个变量的地址和如何获取这两个变量的地址。下面我们就来进行一个简单的实例操作。如何通过指针变量来改变一个变量的值。
#include <stdio.h> int main() { int a = 10; // 定义一个整形变量a=10 int* p = &a; // 定义一个整形指针变量p=a的地址 *p=20;//改变a的值 printf("a的值=:%d\n",a); return 0; }
结果:a的值=20
上述程序中,int* p=&a 意为p=a的地址,*p=20,意为p指向地址的内容=20。也就通过指针变量把原来a=10改为a=20;
编辑
我来解释上图的意思,指针变量p指向变量a的地址。通过操作符*号改变指针p指向变量a的地址里面的值10改为20,那么a就=20了。
*号作符为解引用操作符,它返回指针p所指的对象的值。
本期博客到这里就结束了感谢大家的观看,下期我们再来深入了解指针
编辑
Never give up
UFC征战十几年终于拿冠军,相信你这次只要不放弃一切皆有可能
布鲁克斯之子-奥利维拉