一篇文章带你了解C语言重点——“指针”(C指针详解)

目录

指针是什么?

指针和指针类型

指针类型的定义: 

指针类型的意义:

指针的运算

指针 +- 整数 

指针 - 指针 

野指针 

野指针成因 :

如何规避野指针

指针和数组 

二级指针 

使用指针时常见问题总结 

警告的总结

编程提示的总结


指针在c语言编程中十分重要,它是c语言学习中的重点,同样也是难点,尤其是当我们在学习数据结构的过程中,指针显得尤为重要,无论是线性表、树、队列、栈、哈希表等等都离不开指针的操作,如果你不了解指针,那么在数据结构的学习中会十分煎熬,那么什么是指针呢?

指针是什么?

在计算科学中,指针是编程语言中的一个对象,利用地址,它的值直接指向存在电脑存储器中另一个地方的值,由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将指针地址形象化的成为“指针”。意思是通过它能找到以它为地址的内存单元。

举例说明:

下面这些表达式的值分别是什么?

int a = 112, b = -1;
float c = 3.14;
int *d = &a;//将a的地址存放在d变量中,d就是一个指针变量
float *e = &c; 
abcde
112-13.14100108

通过对表格的分析,a,b,c的内容为int和float类型的值,而d和e的内容为地址,根据表达式我们可以知道d的内容为a的地址,e的内容为c的地址。

经过分析,我们可以得出以下表格,我们可以看出d和e为指针类型,其他都为整形或浮点型

表达式右值类型
a112int
b-1int
c3.14float
d100int *
e108float *
*d112int
*e3.14float

总结: 

1.指针就是变量,用来存放地址的变量;

2.指针是用来存放地址的,地址是唯一标示的一块地址空间;

3.指针的大小在32位平台是4个字节,在64位平台是8个字节。

指针和指针类型

指针类型的定义: 

变量有变量的类型,同样,指针也有指针的类型,如下所示:

char   *pc = NULL;//char类型指针
int    *pi = NULL;//int类型指针
short  *ps = NULL;//short类型指针
long   *pl = NULL;//long类型指针
float  *pf = NULL;//float类型指针
double *pd = NULL;//double类型指针

 这里可以看到,指针的定义方式是:type + *。char类型的指针是为了存放char类型变量的地址,int类型的指针是为了存放int类型变量的地址,那么指针类型的意义是什么呢?

指针类型的意义:

指针的类型(char / int)主要的功能是决定将指针地址+1时前进几个字节,这样确保指针指向的内容与实际内容一致。

例如int类型指针地址+1时,前进4个字节、char类型前进1个字节、double类型前进8个字节...... 

总结:

指针的类型决定了指针向前或向后走一步有多大距离;

指针的类型决定了对指针解引用时能操作几个字节,例如:char* 的指针解引用只能操作一个字节、int* 的指针解引用时可以访问四个字节。

指针的运算

指针的运算有:指针 +- 整数、指针 - 指针、指针的关系运算,下面分别举例说明指针 +- 整数和指针 - 指针类型。

指针 +- 整数 

 指针运算结果

表达式假定p是个指向....的指针*p的大小是增加到指针的值
p+1char11
p+1float22
p+1int44
p+1double88
p+2char12
p+2float24
p+2int48

p+2

double816

举例:

#define N_VALUES 5;
float value[N_VALUES];
float *vp;
for(vp = &value[0]; vp < &value[N_VALUES];)
      *vp++;

 这里定义value是一个长度为5的float类型数组

下标 0   1   2   3   4   
 值
该操作是利用指针操作,*vp++来给数组赋值

开始时vp指向下标为0的位置
下标 0   1   2   3   4   
 值
经过5次循环后,循环中止,此时数组五个下标对应的值均为0

指针 - 指针 

指针 - 指针的操作只有当两个指针都指向同一个数组的元素时,才允许一个指针减去另一个指针,指针相减得到的结果是两个指针在内存中的距离(以数组的长度为单位,而不是以字节为单位),因为减法运算的结果将除以数组元素类型的长度。

例如:p1指向arr[i],p2指向arr[j],那么p2 - p1的值就是j - i的值。

指针 - 指针的操作可以用来实现求字符串长度,代码如下:

int my_strlen(char* s)
{
	char* p = s;//首先令p指向字符串第一个位置
	while (*p != '\0')//最终p指向字符串最后一个位置
		p++;
	return p - s;//p - s即为字符串的长度
}

野指针 

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

野指针成因 :

1.指针未初始化

#include <stdio.h>
int main()
{
	int* p;//局部变量指针未初始化,默认为随机值
	*p = 20;
	return 0;
}

2.指针越界访问

#include <stdio.h>
int main()
{
	int arr[10] = { 0 };
	int* p = arr;
	for (int i = 0; i <= 11; i++)
	{
        //当指针指向的范围超出数组arr的范围时,p就是野指针
		*(p++) = 1;
	}
	return 0;
}

3.指针指向的空间释放 

如何规避野指针

1.对指针进行初始化;

2.注意防止指针越界;

3.指针指向的空间释放即将其置位NULL;

4.使用指针之前先检验指针的有效性。

指针的规范使用举例:

#include <stdio.h>
int main()
{
	int* p = NULL;//先对其进行初始化
	int a = 10;
	p = &a;
	if (p != NULL)//使用前判断其是否有效
		*p = 20;
	return 0;
}

指针和数组 

通过数组知识的学习,我们了解到数组的地址和数组首元素的地址是一致的,由此我们可以得出结论,数组名表示的是数组首元素的地址;

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int *p = arr;//p存放的是数组首元素的地址

数组名可以被当做地址存放到一个指针中,那我们也可以利用指针对数组进行访问。

例如: 

#include <stdio.h>

int main()
{
	int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
	int* p = arr;
	int size = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < size; i++)
	{
		printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p + i);
	}
	return 0;
}

 

由此,我们可以看出p + i其实就是计算数组arr下标为i的地址,因此我们可以直接通过指针来访问数组。

二级指针 

指针变量也是变量,是变量就一定有地址,我们利用指针来存储指针变量的地址,这个指针就称之为二级指针。

例如:

int a = 10;
int *pa = &a;
int **ppa = &pa;

根据上述的定义,a的地址存放在pa中,pa的地址存放在ppa中,pa是一级指针,ppa是二级指针。

对于耳机指针的运算有 :

*ppa通过对ppa中的地址进行解引用,这样找到的是pa,*ppa访问的其实就是pa。

int b = 20;
*ppa = &b;//等价于pa = &b:

**ppa先通过*ppa找到pa,然后对pa进行解引用操作:*pa,找到的为a。

     **ppa = 30;
//等价于*pa = 30;
//等价于  a = 30:  

使用指针时常见问题总结 

警告的总结

1.错误地对一个未初始化的指针变量进行解引用;

2.错误地对一个NULL指针进行解引用;

3.向函数错误的传输NULL指针;

4.未检测到指针表达式的错误,从而导致不可预料的结果;

5.对一个指针进行减法运算,使它非法的指向了数组第一个元素的前面的内存位置。

编程提示的总结

1.一个值应该只有一种意思;

2.如果指针不指向任何有意义的东西,就把它设置为NULL。

 

 

 

 

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Li_yizYa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值