C语言中对于基本指针,数组地址与首元素地址区别的理解

首先,我们又要提出一个枯燥且无心意的问题,指针是什么?对于有一点C语言的指针基础的小伙伴会说指针就是地址,但是这样会使刚开始学的小伙伴存在很多疑问,地址又是什么?所以,为了使小伙伴们加深对于指针的理解,下面我会用更好理解的叙述来解释各类指针的意义。

一.对于指针的自我理解

首先,我们在学习c语言的时候如果想将一个数存入计算机,我们会在程序里定义一个类型变量,可以是int,char,double等等,下面我以定义一个int 类型的变量当做例子。当我在程序中写 int a;时,计算机会给这个变量分配一个地址,当然,这里的地址也只是人为规定的,计算机真正是没有哪个内存单元对应哪个地址的,如果小伙伴们不太理解地址的概念,我们可以把我们住的楼房理解为一块内存条,而每一层的房间号相当于就是我们认为规定的地址,这样,每一层这样依次顺序排列就组成了一栋楼房,而在内存里每一个地址也是大概这样排列,只是不是顺序的排列,因为这里最基本单位是一个字节,所以会跳过一个或多个字节,不同的数据类型所占空间大小不一样当然跳过的地址大小也不一样,就以我下面举的一个整形数组的例子来解释。

从这里我们可以看出,由于int 类型的变量在内存中开辟4个字节的大小来存储,所以,这里数组中a[0]与a[1]的地址相差了四个字节

这里想必大家也就知道了其他类型的变量的存储大小与其地址的关系了。

而后面的指针其实就是定义了一个变量,然后计算机也给它开辟了一个空间,但是这里存储的东西与之前常见的数据类型不同,这里存储的是一个地址,比如我定义一个int a;那么我在定义一个int* p;

然后p=&a;这样p里面存的就是a这个变量的地址了。所以这里的指针p也可以想象成一个特殊的变量,它也就自己的一个地址,它的地址也就是二级指针。下面用对应程序来演示

当然,如果我们想存储一个字符型变量的地址我们就要定义一个char *型的指针来存储它的地址。不同类型的变量的地址我们这里要记住要用不同的指针类型来存储。

二.指针的分类

1.我们存储的普通变量指针可以简单分为字符型的指针和整形指针,其实这里不要被它的概念给弄难了,我的理解就是char *型的指针存储的是一个字符型变量的地址,比如,我这里写char *p="hello";这里p就是一个字符型指针,里面存的是字符串中字母h的地址,这里我们要注意不同,对于字符串类似如下写法就相当于将首字母的地址存入该指针。char *(一个指针变量名)=“一个字符串”。而如果我们定义的是一个字符数组,它的数组名也就是第一个数组元素的地址,这时如果我们想去用地址遍历整个数组,我们就可以对指针p解引用,也就是*p就是第一个数组元素的内容,那下一个元素地址也就是跳过一个该类型的变量大小,可以直接p+1就是下一个数组元素的地址。这样我们依次得到每个元素的地址并且解引用出来就是我们需要的该元素,下面我还是通过程序进行演示。

2.通过以上想必小伙伴们应该已经大概了解了指针的基本意义和用法,下面我来说一下两个易错东西的区分,那就是数组地址首元素地址共同点异同点。我们不如先定义个数组int a[5];那么它的首元素地址就是数组名a或者&a[0],这两个是等价的。而数组地址却是&a;

共同点就是两个的地址值是一样的,但是,我们这里却不能当做是一个东西,一个表示的是整个数组,一个却是表示的数组元素。下面不同点我会在赘述。

不同点就是a+1的意义是数组第二个元素的地址,而&a+1却是跳过一个数组,也就是下一个数组的地址,这个一般用于二维数组的遍历,因为一维数组跳到下一个数组就是不确定的数组,而二维数组可以相当于拆成几个有地址顺序的一维数组。这样二维数组的数组地址加一就可以指向一个确定的数组,还可以指针解引用得到数组中存的数据。下面我我会用程序演示

数组地址和数组首元素地址数值上相同

a+1与&a+1地址数值不同

验证数组地址加1跳过一个数组(用二维数组验证)

这里我要注意一点,二维数组名就相当于一维数组的&a的意思,这里涉及到了数组指针,所以这一节不详细去说,下一节我会把其他的指针,比如数组指针,指针数组,函数指针进行详细解释。

三.简单指针的应用

1.比如可以自己确认一个地址,把该地址上的值改成自己想要的值,但是这样做有些风险,比如一些地址上存有一些系统的重要数据,如果碰巧你要改的地址正好也是存系统数据的地址,那么容易将计算机系统损坏,所以不要轻易尝试,但是这里给出一个例子

*((int *)0x0000000000000000)=12;

这里就是在以0x0000000000000000为地址下存入12;这里(int *)是将0x0000000000000000强转为整形指针地址,在解引用赋值12,这样,我们就在该地址下存入了数字12;但是这里强调千万不要尝试,很容易会使计算机崩溃,只要知道为什么这样操作能实现就行

  1. 在子函数中可以指针传参,比如,我们在子函数中需要传进一个变量的数值,并且在函数中可能会修改这个变量的值,那么,我们能兼顾的方法就是指针传参,也就是子函数的参数传过来的是一个指针这里就可以了。这里可能有一些小伙伴要问了,那我如果要传进子函数一个数组我为什么不可以这样写 void sum(int a[],int b[]),这里要注意,这里在传两个参数的时候系统会按照你传过来的数组在内存中去赋值两个存储数值与传过来一样的数组,尽管这样是可以改值的,但是重新复制数组会浪费一部分内存,没有直接传指针效率高。但是下面验证程序现象也会同时给到大家。

直接传数组改值现象

指针改值的现象

这里,我的实验程序只是很初步的,因为这里主要是为了不弄的复杂,影响大家对于指针的看法,所以希望大家可以看完我的理解可以自己多思考一下,能有自己的见解也会更好。还有就是我这里说的如果哪里存在问题可以进行批评指正。也可以和我探讨一下。

我在c语言专栏会更新下一个关于指针的深入学习,包括数组指针,指针数组,还有指针的嵌套等,希望大家也可以看一看,文章会在近期更新。

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值