网瘾少年带你学习指针(一)

本文介绍了计算机内存的基本概念,包括内存单元、地址以及如何通过地址操作数据。重点讲解了指针变量、取地址操作符、解引用操作符的使用,以及不同类型指针的内存大小和访问权限。通过实例展示了指针加减整数和指针之间的运算规则,包括数组遍历和指针比较。
摘要由CSDN通过智能技术生成

1.内存与地址

在正式开始学习指针前,我们先来了解一下内存。

我们都知道,电脑中的数据是储存在内存中的,但是有没有想过我们在使用这些数据时电脑是怎么能精确的找到这些数据的呢?比如我们创建了一个整形的数据,然后使用了一个赋值语句赋给它一个别的值,电脑是怎么能精确找到你想要修改的值呢?

这是就要提到我们的内存了,在计算机中,我们将内存分为一个个的内存单元,一个内存单元的大小是一个字节,我们在电脑中的数据就是储存在这一个个的内存单元中。

电脑为每一个内存单元都添加了一个编号,这些编号就是地址,而我们的电脑就是通过这个地址来找到我们想要的数据的。在每个数据创建时,电脑都会自动为其分配内存,同时也就分配了地址,通过地址来找到这个数据对其进行各种修改。

这个地址也就是我们本次要了解的东西。

2.指针变量与地址

2.1 取地址操作符 &

在c语言中,我们创建一个变量实际上是在向内存申请一块空间来储存这个变量比如:

这里我创建了一个变量a,然后当我们调试起来,通过调试里面的内存窗口来查看a的地址。 

我们刚刚说过一个内存单元是一个字节,a是一个整形,我们都知道整形是占4个字节的内存,所以我们看到的四个地址都是a所占用的内存空间 。

当我们创建一个变量,但是我不通过查看调试能不能知道它的地址?这时候就涉及一个操作符,取地址操作符 & ,顾名思义,通过这个操作符我们就可以将一个变量的地址取出来。

这时候有人会有疑问,a不是有四个地址吗,那你这个取地址符号难道能一次性把四个地址都取出来吗?答案是否定的,取地址操作符在使用时只会将a较小的地址给取出来。即将0x00D5F744取出。

但是取出来确是是取出来了,我该怎么去使用它,或者说怎么去储存它?

 这时候就到我们本期的主角出场了,我们想要使用储存一个地址,就要使用一个指针变量来储存它。就比如我想要储存这个整形的地址:

在这个程序里,pa就是一个指针变量。

2.2指针类型的理解 

pa表示的是变量名,这个变量名是你自己取的。没什么好说的,我们重点来理解一下前面的类型。

int * 表示这个指针变量是一个整形指针。其中的 * 表示这个变量是一个指针变量。int 不是表示它是一个整形,而是指这个指针储存的地址的内容是一个整形,因为 a 是一个整形变量,而 &a 表示这块内存是指向 a 的,所以这个指针变量储存的地址的内容是一个整形,所以这个类型是int。

那么我们就可以推断出指针变量的 创建应该是

地址所储存的对象的类型 * 变量名;

那么一个字符指针、单精度浮点型指针、双精度浮点数指针就是:

char* p1;
float* p2;
double* p3;

要注意的是指针其实是指一个地址,但我们平时所说的指针是指针变量。

2.3 解引用操作符 *

当我们有了一个指针后,我们该怎么样去使用这个指针,前面不是说有了这个数据的地址就能根据这个地址去改变这个数据吗,那么该怎么操作呢?

这个时候,解引用操作符站出来了,我们通过解引用操作符就能拿到指针所指向的内容,并对它进行修改。

在这里,我通过两种方式修改了a的值,一种就是变量赋值的方式,另一种就是通过指针解引用,通过解引用找到a的本身,然后修改a的值。

解引用就相等于找到a的本身,可以理解为:

*pa = a

 这不是赋值啊,是单纯的他它们两个等价。我们可以将 *pa就理解为a,我们在打印a时也可以通过 *pa来实现。

2.4 指针变量的大小

当我们创建一个指针变量以后,有没有考虑过它所占的内存大小。我们知道,一个整形所占内存大小是4个字节,一个字符类型所占内存大小是1个字节,那一个整形指针,或者是一个字符指针所占的大小是不是也是4个字节和一个字节呢?

如我们所见,无论是整形指针int *,字符指针 char * 还是双精度浮点型指针 double * 的大小都是4个字节,那么我们可以得出一个结论是指针的大小与什么类型是无关的。

指针的大小只跟操作平台有关,当我们是在32位平台时,指针变量的大小是4个字节,当我们在64位平台时,指针的大小就是8个字节。只要是同一种类型的平台,无论是是什么类型的指针,大小都是4个字节。

3.指针变量类型的意义

可能有人会疑问,既然在同一平台下指针的大小都一样,那还要类型干什么,直接起个统一的名字来表示指针,比如就叫 zhizhen 多好,还要搞那么多类型。

先说结论,指针的类型代表了指针的访问权限大小。

3.1指针的解引用

直接上代码:

 

在右半部分中前四个地址就是n在内存中的值,因为内存中的值是16进制显示的,所以我们也将它以16进制的方式来初始化,这样有助于观看。

可以看到当我们用 int *变量去修改n时,它的四个字节都被变为0了,但当我们用char *类型的指针去修改时就只能将最上面的那个修改掉。

所以说指针类型就是指针能访问的字节大小,如果是一个整形指针,那么它能访问的字节数就是4个,这就是指针类型的意义。

3.2 指针+-整数

了解了指针的意义以后,我们来了解一下指针的运算,如果一个指针去 +1是什么,-1又是什么,不同类型的指针在+-整形上会不会有不同?

 来观察一些地址的变化:

 我们来算一下,两种不同类型的指针在+1后地址发生的变化。

这里地址打印出来是一个16进制的数字,pa的地址先是,00DBFD08,后面变成了00DBFD0C,中间加了一个4,因为16进制里面A是10,然后以此类推,C就是12,所以是加了4。再看pb,最后一个数字由三变成了4,说明加了1。

通过这些地址的变化,我们可以看出来,指针加减整数实际上是跳过整数个指针所指向的类型的数据,整形指针+1就是跳过一个四个字节,字符指针+1就是跳过一个字节。

那么我们可以得出结论就是:指针加减整数表示指针前移或后移的大小。

4.指针的运算

4.1指针+-整形

那么可能有人会疑问,这个指针+-整数有什么用呢?

我们就以数组为例来演示一下指针+-整数的用处:

我们创建一个整形数组,如果我们拿到了这个整形数组首元素的地址,那么通过指针+整数就可以找到这个数组的所有值。

在这个程序种,我通过&arr[0]找到数组第一个元素的地址,并将它赋给了指针p,然后在一个循环中,用p + i 来找到整个数组,因为i的值不断在增加,这样我们就可以不断跳过 i 个整形来找到整个数组中的数据。

4.2 指针-指针

指针除了能+-整数以外还能减指针,就是两个指针做差。

指针减指针的结果是一个整形,你可能会疑惑,为什么两个地址之间的差值是一个整形呢,实际上,这个整形是两个指针之间的元素个数:

在这里,我取出了数组第一个元素的地址,以及第四个元素的地址,将他们两个做差,最后得出的结果是3,由此我们可以看出指针-指针的结果是两个指针之间的元素个数。

但是这次我是第四个元素的地址减去第一个元素的地址,肯定是第四个元素的地址大吧,那我要是用小的减去大的会怎么样?

这里可以看到结果是-3,结果是负数,那看来我们刚刚的结论稍微有点不正确。

最终的结论是:指针-指针的结果的绝对值是指针之间的元素个数。

要注意的是,指针之间是没有相加的操作的。

4.3 指针比较大小

 指针是一个地址,但是指针之间是可以进行比较的,比较的方式是比较他们的地址的大小,因为地址实际上也是一串数字,在进行指针的比较时,实际上就是比较这两个地址的大小,地址越大,就说明这个指针比另一个指针大。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值