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

Posted chris只会写bug

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了☀️☀️☀️不会还有人学不会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;
}

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

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


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

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


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

以上是关于☀️☀️☀️不会还有人学不会C语言中的指针和数组吧?Chris带你走进并玩转指针与数组的世界☀️☀️☀️的主要内容,如果未能解决你的问题,请参考以下文章

不会吧,不会吧,不会还有人不知道❤️Python给图片加水印❤️超级简单哦

☀️C语言函数传参の结构体数组篇☀️

☀️C语言函数传参の结构体数组篇☀️

搞透C语言指针那年我双手插兜, 不知道指针是我的对手

Golang✔️走进 Go 语言✔️ 第十一课 指针

Golang✔️走进 Go 语言✔️ 第十一课 指针