C语言 指针

C语言 指针

什么是指针:
指针是一种数据类型使用它可以定义指针变量,这种变量存储的是整数,这些整数代表了内存编号,每个数字代表一个字节,使用指针变量可以访问对应的内存,具体访问多少个字节由指针类型决定。
注意:指针的类型只决定指针访问内存的字节数,而指针本身的字节数由系统位数决定,32位系统占4字节,64位系统占8字节。

使用指针的几种情况

从理论上讲,指针可以访问任何位置的内存,但对于绝大部分的内存,我们并没有权限访问,因此非常容易产生段错误,因此只有在合适的情况下才会使用指针。

  1. 函数之间共享局部变量
    函数传值是单向的值传递即由实参传给形参,形参并不会返回值给实参。而全局变量由于其浪费内存,可能造成命名冲突的缺点,不适合用于共享,所以指针是函数之间共享局部变量的最好选择。
  2. 函数需要多个返回值
  3. 使用指针可以提高函数的传参效率
    函数传参是内存拷贝(值传递),当变量的字节数较多时,指针的传递效率更高,只需要4/8字节。但这样就带来了变量被修改的风险。可以用const配合指针来保护变量。
  4. 配合堆内存使用
    堆内存无法取名(无法与标识符建立映射关系),因此必须与指针使用。

如何使用指针

定义指针变量:类型* 指针变量名;

  1. 由于指针变量的用法和普通变量不同,为了避免与普通变量混淆,指针变量一般以p结尾。
  2. 指针变量与普通变量一样默认值是随机的(野指针),为了安全一定要初始化,一般初始化为NULL(空指针)。
  3. int* p1,p2; p1是指针变量,p2是int型变量
    int *p1,*p2; p1,p2都是指针变量

指针变量的解引用:*指针变量
通过指针变量中存储的内存编号去访问内存,具体访问多少个字节由指针变量的类型决定。
该过程可能产生段错误,但要从指针变量赋值的步骤去寻找原因。

指针的运算:
指针变量中存储的是整数,理论上整性数据能使用的运算符,指针变量都可以使用,但只有以下三种运算有意义

  1. 指针 + n == 指针 + (n * 字节数)
  2. 指针 - n == 指针 - (n * 字节数)
  3. 指针 - 指针 == 指针 - 指针 / 字节数

使用指针要注意的问题

空指针:
指针变量的值为NULL的指针被称为空指针,这种指针不能解引用,否则会产生段错误。
大多数系统的NULL是0地址,可以把指针变量当逻辑值使用,但不建议这样。
为了避免空指针导致的段错误,当使用来历不明的指针时应判断是否是空指针。

野指针:
指针变量的值是随机的,不确定,这种指针称为野指针,使用野指针不一定会立即出错,与空指针相比,它的危害性更大。
无法判断一个指针变量是否是野指针。所以为了避免野指针导致的bug,我们应该避免产生野指针。
1.定义指针变量时一定要初始化
2.指针变量所指向的内存被释放或销毁后,指针变量要及时的置空。
3.函数不返回局部变量的地址。

指针与const

const int* p; 保护目标,不被指针解引用修改
int const * p; 同上
int* const p; 保护指针变量p不被修改
const int * const p; 既保护p也保护p
int const * const p; 同上
Const int const
p; 错误用法

指针数组与数组指针

指针数组: 由指针变量组成的数组,它的身份是数组,成员是指针变量。
类型* 变量名[n];
int* arr[10];
数组指针:它的身份是个指针,专门用来存储数组的地址。
类型 (*变量名)[n];
int (*arr)[5];
注意:数组指针使用数组的字节宽度作为移动单位

void指针与函数指针

void指针:

  1. 以1字节为移动单位
  2. 不能解引用
  3. 在C语言中可以与任何类型的指针自动类型转换,也被称做万能指针
  4. 一般用作函数的参数和返回值
    函数指针:
    函数会被翻译从二进制指令存储到代码段,函数名就是这段指令的首地址。
    可以定义特殊的指针变量存储函数的首地址,这样就可以把函数当前数据进行传递。
    用来存储函数地址的指针变量叫做函数指针。
    如何定义函数指针:
    普通函数声明: int fun(int num);
    函数指针声明: int (* funp)(int num);
    函数指针赋值: int (* funp)(int num) = funp;
    当我们把函数作为数据传递时,被调用函数可以通过函数指针调用我们以参数形式提供的函数,这种模式叫回调模式。比如qsort(),bsearch()

二级指针

一级指针用于存储普通变量的地址,二级指针用于存储一级指针变量的地址,当跨函数共享一级指针变量时,需要使用二级指针。
定义二级指针:
类型** 变量名_pp;
二级指针赋值
Int num;
Int* p = #
Int** pp = &p;
二级指针解引用:
*pp == p;
**pp == *p

指针与数组的关系

数组名就是数组空间的首地址,是一个常量地址,可以把它看作常指针,可以使用解引用的语法访问其成员,指针变量也可以使用[]进行解引用Arr[n] == * (arr + 1);
与普通指针的区别:
1.数组名时常量,普通地址是变量
2.普通指针变量有自己的存储空间,用来存储内存编号,它与目标内存是指向关系
3.数组没有自己的存储空间,它就代表数组空间的首地址,它与数组内存是映射关系
4.对数组名取地址结果还是数组名的值
Int arr[5];
Arr <=> &arr;
Arr 类型 int*
&arr 类型 int (*) [5]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值