详解指针与数组(😉学不会退学费😉)
- 一、✨指针基本概念✨
- 二、🎃为什么要有指针🎃
- 三、🎠如何理解编址🎠
- 四、👑指针的内存布局、解引用👑
- 五、🎮如何将数值存储到指定的内存地址🎮
一、✨指针基本概念✨
先从一个小例子开始
#include <stdio.h>
int main()
{
//定义一个变量并做初始化
//开辟空间 赋值
int a = 10;
//使用的是a的空间:左值
a = 20;
//使用的是a的内容:右值
int b = a;
//同样一个a,在不同表达式中,名称虽然一样,但是含义完全不同
return 0;
}
结论:
定义一个变量,本质是在内存中根据类型来进行开辟空间
有了空间,就必须具有地址来标识空间,来方便CPU进行寻址
有了空间,就可以把数据保存起来
指针是什么 |
指针:指针就是地址!
地址的本质:数据,可以被保存在变量空间里面
指针变量:保存指针(地址)数据的变量
指针与指针变量区别 |
左值:左值是用来指明一个对象的表达式,最简单的左值就是变量名称,它可以出现在赋值运算符的左边
右值:可以出现在赋值运算符右边而不是左边的表达式,例如,常量和算术表达式
只有指针变量被用为右值的时候,此时指针变量才等于指针
解释一下下面各个语句表达的意思
int a = 10;
int *p = &a;
p = 10;
int *q = p;
*p = 10;
int b = *p;
结论:
1、指针就是地址值
2、指针变量在C中是变量,要在特定区域开辟空间,用来保存地址数据,还可以被取地址
3、严格意义上来说两者不同,但是我们一般在说时,一般将指针误认为指针变量
二、🎃为什么要有指针🎃
在32位机器下,最多能够识别多大的物理内存 |
CPU按字节寻址 |
结论:
指针存在的作用简单来说就是提高查找定位效率
三、🎠如何理解编址🎠
计算机中有很多硬件单元,各个硬件单元之间都是协同工作,所谓协同就是相互之间要能够进行数据传递
硬件与硬件之间都是相互独立的,我们需要用线连起来
CPU与内存之间也是相互独立的,但是要进行数据的交互,需要用数据总线、地址总线等其他线连起来
CPU在访问内存中某个字节空间时,由于内存中的字节很多,所以必须要对内存进行编址
计算机中的编址,并不需要对每个字节的地址进行记录,其实在设计计算机硬件电路的时候就已经完成了
CPU与内存的数据传输 |
简单来理解:
32位机器有32跟地址总线,每根线有两种状态,表示1、0(有无电脉冲)
一根线就能表示2种含义,两根线就能表示4种含义,32根地址线就能表示2^32种含义,每一种含义代表一个地址
地址信息被下达给内存,在内存内部,就可以找到该地址对应的数据,该数据通过数据总线传入CPU内寄存器
四、👑指针的内存布局、解引用👑
指针的内存布局 |
int a = 10;
int* p = &a;
&a取出的是低处的地址,一定不是中间的地址
指针解引用 |
*p,取出p中的地址,访问该地址指向的内存单元(通过指针变量访问,本质是一种间接寻址的方式)
总结:
在相同类型情况下,对指针进行解引用,代表指针所指向的目标(这里*p指向的目标是a)
我们进入更进一步的思考,*p中的p变量代表的是左值,还是右值???
*p对p变量进行解引用操作,访问的是p的右值
int* p = NULL 和*p=NULL的区别 |
int* p = NULL;
- 定义一个指针变量p,这个指针的数据类型是int
- 在定义变量的同时,将p的值设置为NULL(0)
- 这里只是指针p的值为NULL,但是*p没有赋值
int* p;
*p = NULL;
- 定义了一个指针变量p,这个指针的数据类型为int
- p本身为多少并不知道,p有可能是保存的非法的地址,那么将*p设置为NULL,将是访问非法地址
五、🎮如何将数值存储到指定的内存地址🎮
栈随机化
#include <stdio.h>
int main()
{
int a = 0;
printf("%p\n", &a);
return 0;
}
可以发现每一次对a(局部变量)取地址,打印出来的地址不同,这就是栈随机化
总结:
使用C语言定义的局部变量,在每次运行的时候,地址都是不同的。经过试验发现, 定义全局变量,每次更改代码,地址也会发生变化,所以
我们不可以直接通过地址数据对变量进行访问
#include <stdio.h>
int main()
{
int a = 100;//假设100的地址为0x11223344
*((int*)0x11223344) = 200;
printf("%d\n", *((int*)0x11223344));
return 0;
}
这里我们使用了直接寻址,发生了报错
#include <stdio.h>
int main()
{
int a = 100;
int* p = &a;
*p = 200;
printf("%d\n", *p);
return 0;
}
这里使用了间接寻址,程序运行正常
目前主流的编译器和操作系统,为了安全,已经有了很多内存保护的机制,利用栈随机化的技术来防止黑客对用户数据的预测
😁😁😁觉得对自己有帮助的小伙伴可以点个赞哦😁😁😁
👉👉👉有误的地方也可以在评论区讨论哦👈👈👈
离开前,别忘了👍关注💡收藏💖
希望本文能够对大家有帮助~!