C语言指针的几个注意点

什么是指针

指针是C语言是一种特殊的数据类型,可以定义指针变量,里面存储的是整数,代表的是内存编号。

每个整数对应一个字节(8个二进制位),通过这种编号可以访问对应的内存,具体访问多少个字节由指针的类型决定。

32位系统一个指针变量大小4字节

64位系统一个指针变量大小8字节

为什么使用指针

从理论上讲指针可以访问任何任何位置的内存,但绝大多数的内存我们没有访问权限,因此非常容易产生段错误,建议只在合适的时候才使用指针。

1、函数之间协调工作时需要共享局部变量

2、使用指针可以提高传参效率,函数之间需要传递较多字节数的变量(如结构体)时,传递变量的地址效率更高。

3、堆内存无法取名字(无法与标识符建立映射关系),必须与指针变量配合。

使用指针需要注意的问题

1、空指针:指针值为NULL的指针叫空指针,不能运行解引用,一旦解引用空指针就会产生段错误。
NULL在大多数系统的值为0,该地址储存操作系统重启的数据。
NULL也被当作错误标志,如果函数的返回值是指针类型,当它的值是NULL时说明执行出现错误。

如何避免空指针产生的段错误:对来历不明的指针进行解引用前要先判断是否为空

2、野指针:指针变量的值是不确定的,随机的,未知的,这种指针被称为野指针。

​ 对野指针进行解引用的后果:一切正常 (运气好)、段错误 (大概率)、脏数据 (堆内存申请的越多,脏数据可能性越大)。

如何避免野指针产生的错误:
野指针是无法被判断出来的,使用野指针不一定立即出错,所以危险性比空指针更大。
所有的野指针都是人为制造出来的,只有不制造野指针,才能避免使用野指针。

可能产生野指针的情况:
a、定义指针变量时没有初始化。
b、函数返回了局部变量的地址。
c、资源已经被释放,但是指针变量还在继续使用而没有及时置空。

指针运算

指针变量存储的是代表内存编号的整数,使用%p占位符可以以十六进制显示指针变量的值。

理论上凡是整型数据可以使用的运算符,指针变量都可以使用,但是只有以下运算是有意义的:

​ 指针+整数n 相当于指针变量向后移动n个元素的宽度,移动了sizeof(类型)*n个字节

​ 指针-整数n 相当于指针变量向前 移动n个元素的宽度,移动了sizeof(类型)*n个字节

​ 指针-指针 两个指针之间相隔多少个元素,结果是(指针-指针)/sizeof(类型)

*万能指针(void

1、不能解引用,必须先转换成其他类型指针才可以解引用访问内存。
2、运算是以1字节为单位。
3、它可以和任意类型的指针进行自动类型转换(C语言)。一般用作函数的参数和返回值。
当作函数的返回值和参数不确定是什么类型的指针,可以使用它。

指针与数组名

相同点:

1、数组名其实是一个特殊类型的常指针(数组空间的首地址),不能修改它的值。可以使用解引用的方式访问数组的元素。

反过来指针也可以使用[]进行解引用。

int arr[5] = {1,2,3,4,5};
for(int i=0; i<5; i++)
{
	printf("%d", *(arr+i)); //打印的是数组arr中第一到第五个元素,arr[i] <=> *(arr+i)
}

不同点:

1、数组名是常量,指针是变量
2、指针有自己的存储空间,里面存的是内存地址。
数组名没有自己的存储空间(它自己就是地址)。
3、指针与目标内存是指向关系
数组名与目标内存是映射关系
4、对数组名取地址结果还是数组名的值

指针数组与数组指针

1、指针数组:

首先是个数组,由指针变量组成的数组。

可以配合堆内存,模拟不规则的二维数组,可以根据需要节约内存

int* arr[n];	//类似普通数组

2、数组指针:

首先是个指针,专门用于储存数组的地址。

可以配合堆内存,模拟规则的二维数组,使用方便。

注意:数组指针,一旦做加1,加的是整个数组的宽度。

int (*p)[n];    //指针p指向一个长度为10,存储int类型的指针

指针与const

const在*之前是保护目标

const在*之后是保护指针

const int* p;   	// 保护目标,不能通过指针修改目标
int const* p;   	// 同上

int* const p;   	// 保护指针变量不被修改

const int* const p; // 既保护指针变量也保护目标
int const* const p; // 同上

函数指针

c代码会被编译器翻译成二进制指令存储在代码段中。

一个函数就是一块代码段中的数据,函数名就是这块数据的首地址。

可以说函数名就是个特殊的地址,是个常量指针。

可以定义指针变量存储函数的地址,专门指向函数的指针变量叫做函数指针。

使用函数指针,可以把函数当作一段数据,在函数之间传递,从而实现回调模式

//返回值类型 (*函数名_fp)(形参列表);  
//函数指针
typedef void (*FP)(int, int );	

二级指针

一级指针(普通指针),用于存储普通变量的地址。
二级指针用于存储指针变量的地址。
跨函数共享一级指针时可以使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值