☀️☀️☀️不会还有人学不会C语言中的指针和数组吧?Chris带你走进并玩转指针与数组的世界(一)☀️☀️☀️


一、✨指针基本概念✨

先从一个小例子开始

#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
  1. 定义一个指针变量p,这个指针的数据类型是int
  2. 在定义变量的同时,将p的值设置为NULL(0)
  3. 这里只是指针p的值为NULL,但是*p没有赋值
int* p;
*p = NULL
  1. 定义了一个指针变量p,这个指针的数据类型为int
  2. 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;
}

这里使用了间接寻址,程序运行正常

目前主流的编译器和操作系统,为了安全,已经有了很多内存保护的机制,利用栈随机化的技术来防止黑客对用户数据的预测


😁😁😁觉得对自己有帮助的小伙伴可以点个赞哦😁😁😁

👉👉👉有误的地方也可以在评论区讨论哦👈👈👈


离开前,别忘了👍关注💡收藏💖
希望本文能够对大家有帮助~!

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值