指针没学好,点开文章,带你重新学习指针!

一、什么是指针

        指针指针难道是针吗?哈哈哈,当然不是,有一种更加好理解的说法,就是内存的地址,它可以指向目标内存的位置,方便我们使用,就像一栋楼,每个房间都有一个门牌号,方便我们去寻找。

二、指针变量

        指针变量,就是储存指针的变量。在C语言中创建变量其实就是向内存申请空间,而每一块空间都有其自己的地址,而这个地址有时候也是需要 存储起来,⽅便后期再使⽤的,储存地址的变量就是指针变量。

        既然要取地址进行储存,那么用什么去取地址呢?答案是取地址操作符&。例:

                       

在这我们采用打印的方式打印了a的地址。

指针变量类型

        指针变量同数据一样有多种类型,例如:int * pa = &a;int*,*表示这个变量是指针变量,int代表着pa这个指针变量指向的是整型(int)这中类型的对象。

解引用操作符 *

        那么有了指针变量,我们应该怎样使用呢?有了指针变量中储存的地址,就可以通过地址(指针)找到地址(指针)指向的对象,从而进行各种操作。这里就必须学会一个操作符叫解引用操作符*了。

                  

        从上图可以看出,*p是等价于a的,*p 的意思就是通过p中存放的地址,找到指向的空间, *p其实就是a变量了;同样的,也可以以此对a中的值进行操作。

                          

指针变量的大小

        指针变量的大小是固定的,与变量中储存的内容无关,只与操作平台有关,如果是32位平台下就是4个字节,64位平台下就是8字节。

指针类型的意义

        指针类型的不同对我们进行操作是有影响的,先看如下代码:

                          

可以看到,指针类型的不同,当对其进行加一的操作的结果是不同的,int*(整型)类型地址变化了4个字节,char*(字符类型)变化了一个字节。结论:指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节),决定了指针向前或者向后⾛⼀步有多⼤(距离)。

void*类型指针

        在指针类型中有⼀种特殊的类型是 void* 类型的,可以理解为⽆具体类型的指针(或者叫泛型指 针),这种类型的指针可以⽤来接受任意类型地址。但是也有局限性, void* 类型的指针不能直接进 ⾏指针的+-整数和解引⽤的运算。

const修饰指针

        指针变量是可以修改的,但如果我们希望使用地址,却又不希望修改地址中的内容时,就需要用到const与修饰我们的指针变量。(const也可以修饰其他变量,以保持其不被随意改变,但实际上我们还是可以利用他的地址对其进行修改)

        注意:const放置的位置不同其修饰的内容也是不同的!

        例:int* const p;中的const修饰的是p,即指针的指向不可修改。int const * p;中的const修饰的是*p,即p所指向的内容不可修改。但如果是这样:int const * const p;两者都被修饰,则都不可修改。

指针运算  

        指针的基本运算有三种,分别是: 1、指针+- 整 2、 指针-指针 3、指针的关系运算

         指针+- 整:上面已经说过了,不同的类型,加减整数其操作的大小是跟指针类型有关的;

        指针-指针:两个指针相减得到的是两个地址间的元素个数。如下图:

                   

字符串“abcdefg”中有7个元素(字符串末尾有个隐藏的\0)。

        指针的关系运算:其实就是指针的大小比较。

野指针

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

        成因:1.指针未初始化 2.指针越界访问 3.指针指向的空间被释放

        规避野指针:1.初始化指针,如果明确知道指针指向哪⾥就直接赋值地址,如果不知道指针应该指向哪⾥,可以给指针赋值NULL. NULL 是C语⾔中定义的⼀个标识符常量,值是0,0也是地址,这个地址是⽆法使⽤的,读写该地址 会报错。

        2.小心指针的越界访问。

        3.指针不在使用时,及时置为NULL,指针使⽤之前检查有效性(检查其有效性,可以使用assert断言,后面再说)。

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

assert断言

        assert.h 头⽂件定义了宏 assert() ,⽤于在运⾏时确保程序符合指定条件,如果不符合,就报 错终⽌运⾏。这个宏常常被称为“断⾔”。#include<assert.h>

        如果已经确认程序没有问 题,不需要再做断⾔,就在 #include 语句的前⾯,定义⼀个宏 NDEBUG。像这样:#define NDEBUG。assert() 的缺点是,因为引⼊了额外的检查,增加了程序的运⾏时间。

指针的使⽤和传址调⽤

        例如:写⼀个函数,交换两个整型变量的值(注意是交换两个变量地址里的值)

                  

三、使⽤指针访问数组

        指针访问数组,首先我们的知道数组名这一概念。

        数组名:通常情况下数组名就是数组⾸元素(第⼀个元素)的地址,但也有一些例外,比如:sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节 。&数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的)。

四、二级指针

        指针的指针就是二级指针,由此还有三级四级等,不过用的比较少。

                          

对二级指针进行两次解引用就等价于原内存中的数据了,即**p2 == *p1 ==a。

五、指针数组

        指针数组,用于存储指针的数组 != 数组指针。类比整型数组(存放整型的数组)、字符数组(存放字符的数组)。

---------------------------------------------------------------------------------------------------------------------------------指针的内容就先说这么多了,后续还会更新更多的有关指针的内容,加油加油!!!

  • 54
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值