初阶指针讲解


前言

本文章为初阶指针讲解,进阶会在后面补一篇讲解进阶


提示:以下是本篇文章正文内容,下面案例可供参考

一、指针是什么?

指针要了解的两个要点:

        1.指针就是内存中一个最小单位的编号,也就是地址

        2.在我们平时说的指针,通常是指指针变量,也就是用来存放内存地址的变量

        总结:指针就是地址,口语中的指针通常是指指针变量

         那么我们为什么需要指针?在内存中,最小的单位是字节,而我们如果需要存储数据,那么就需要划分内存,当我们将我们所需要的数据随便放入所划分的内存空间中,当我们需要使用它的时候,我们怎么找到它,如果一个一个的找,太耗时间了,所以我们将内存划分为一个个字节,并将其编号,这样当我们放入数据后,使用时就不会耗费时间。

        指针变量,用来存放地址的变量。(存放在指针变量中的值都被当做地址来处理)。

        那么我们是怎么编地址的呢?

        对于32位机器,假设有32根地址线,那么每根地址线会产生高电平和低电平(就是高低电压),也就是1和0。

        那么32位机器所产生的地址就是:

00000000 00000000 00000000 00000000

00000000 00000000 00000000 00000001

...........................

11111111 11111111 11111111  11111111

        那么这里就有2的32次方个地址,每一个地址是一个字节,那么我们就可以给2^32Byte==2^32/1024KB==2^32/1024/1024MB==2^32/1024/1024/1024GB==4GB

        就可以给4G的空间编址

        64位机器同理。


二、指针和指针类型

这里我们来讨论一下指针的类型。

我们都知道,变量拥有不同的类型,那么指针是否有不同类型?

准确的说:有

现在给你一条代码:

int num = 10;
	p = #

        你觉得p的类型是什么?

        我们给指针变量相应的类型。

        也就是我们所要存放的数据的类型是什么,就给指针什么类型。

        有人可能会觉得,在32位,或64位机器上,所有地址的编号都是由32个0或1,或者由64个0或1组成,所有的指针大小都是一致的,为什么要分类型呢?

指针类型的意义:

 

         这里我们给num赋值10,查看内存中为图中右边第一行,其十六进制就是00 00 00 0a

 

        然后我们通过解引用操作,将num的值改为0,这是标准的写法,但是我们如果将p的类型改为char会发生什么?

       我们重新声明变量:  

        通过图我们看见了,如果将pa的类型由int*改为char*时,本来我们访问的是四个字节,但是现在却只访问并修改了一个字节,这就是我们为什么要区分指针类型。

        通过这里我们可以明白一个道理,指针的类型代表了我们可以访问修改多少字节。

 

        当我们使用不同的指针变量来存放地址的时候,并将其打印,可以发现,它们的地址是相同的,但是在使用pa+1和pc+1的时候出现了变化,我们可以看见,进行加一操作后,与原地址相差的大小就是指针变量类型的大小,由此我们可以总结出,指针变量类型决定了进行+1操作时步长。 

2.1.指针+-整数

代码如下(示例):

int main()
{
    int n=10;
    char *pc=(char*)&n;
    int *pi=&n;
    printf("%p\n",&n);
    printf("%p\n",pc);
    printf("%p\n",pc+1);
    printf("%p\n",pi);
    printf("%p\n",pi+1);
    return 0;
}

 上面其实已经讲了指针加减整数的效果是什么,这里就直接总结下:

        指针的类型决定了指针向前或者向后可以走多长。

2.2.指针的解引用

代码如下(示例):

int main()
{
    int n=0x11223344;
    char *pc=(char *)&n;
    int *pi=&n;
    *pc=0;    //重点在调试的过程中观察内存的变化
    *pi=0;    //重点在调试的过程中观察内存的变化
    return 0;
}

总结:

        指针的类型决定了,对指针解引用的时候有多大的权限(可以操作多少个字节)

        比如:char*解引用时只能操作一个字节,而int*解引用的时候可以操作四个字节

三、野指针

                概念:野指针就是指针指向的位置是不可知的(随机的,不正确的,没有明确限制的)

3.1.野指针的成因:

3.1.1.指针未初始化

         这里的指针变量p中我们并未存放地址,是未知的,随机的,但是我们这里解引用了他并赋值20,这是错误的,这里的p就是野指针。

3.1.2.指针越界访问

        这里的arr数组的下标是从0到9,也就是说,我们只能操作这10个元素,但是在for循环中,i代表下标,i的值是从0到11,当i=10的时候,此时我们操作的空间已经不属于arr数组了,我们并不知道操作的到底是什么,这就是指针越界访问。

3.1.3.指针指向的空间被释放掉了 


        注意!这里的自定义函数中a的空间只存在于该函数中,意思就是只有我们进入函数才创建,出函数时就会还给操作系统 ,这里我们虽然能够成功的打印a的值,但是这种行为是非法的,所以不要使用这种方法。

3.2.如何避免野指针

 1.指针初始化

        1.知道要初始化什么地址时,直接初始化

        2.不知道初始化什么时,暂时初始化为NULL(空指针)

2.小心指针越界

        1.看仔细数组的下标范围

3.指针指向空间释放,及时置NULL

        

4.避免返回局部变量的地址

5.指针使用之前检查有效性

四、指针运算

4.1指针+-整数

                这个已经在类别讲过了,如有需要向上翻看。

4.2指针-指针

         这里我们通过数组下标为9的元素地址减去下标为0的元素地址,得到的结果为九,那么我们看看下标0到9之间的元素个数也为9,那么我们得出,指针减指针,得到的是两个指针之间的元素个数。

注意!指针-指针的写法必须保证两个指针都是指向的同一块空间。

4.3指针的关系运算

1.地址是有大小的

2.指针的关系运算就是比较指针的大小

五、指针和数组

        指针和数组之间的关系是什么呢?

        指针变量就是指针变量,不是数组,指针变量的大小可以是4/8个字节,专门是用来存放地址的。

        数组就是数组,不是指针,数组是一块连续的空间,可以存放一个或多个类型相同的数据。

        联系:数组中,数组名其实就是首元素地址,数组名 == 地址 == 指针

六、二级指针

 

        像我们上面所写的指针,都是一级指针,指针变量也是变量,只要是变量,那么就都有地址, 

 

        如果我们将一级指针的地址存放在一个指针变量中,那么这个指针变量就叫做二级指针。

七、指针数组

注意 !指针数组还是数组,不是指针。

        这里我们将arr1、arr2、arr3的地址放入数组parr中,这时的数组parr就叫做指针数组,那么指针数组有什么用呢?指针数组能够让我们快捷的操作其他数组。 

总结

        简单讲解了指针的相关知识点,对于指针的初阶知识差不多说完了,多介绍了指针数组的概念,指针的使用能够让我们根加方便的完成一个程序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值