指针进阶——1

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

指针进阶讲解


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

一、指针是什么?

二、指针的分类

1.字符指针

在指针的类型中我们知道有一类指针类型为字符指针——char*  ;

一般的使用:

int main()
{
    char ch='w';
    char* pc=&ch;//pc为字符指针
    *pc='w';

    return 0;
}

在这里pc就是字符指针

当然,这里还有另外一种写法:

int main()
{
    const char *pstr="hello bit ";//这里是把一个字符串放入了pstr中了吗?
    printf("%s\n",pstr);
   return 0;
}

         在这里有大部分的同学都会认为我们是把hello bit 放入了字符指针中,但是本质上是把字符串hello bit 的首位字符的地址放到了字符指针pstr中。

        当然还有一些同学会将const省略掉,当然我们最好不要讲其省略掉,在这里的字符串hello bit是常亮字符串,是存储在内存的静态区的,它的地址是不变的,所以我们需要加一个const来修饰指针pstr。请一定要注意,这里的const所修饰的是*pstr,而不是pstr。

 在这里的输出结果是什么呢?

        我们来进行分析:

        首先我们讲字符串hello bit 放入了字符数组str1和str2,同时我们将字符串的首个元素的地址放入了字符指针str3和str4中,在这里我们需要判断的条件是str1与str2是否相等,首先我们需要明白这里的str1和str2代表的意义是什么,我们在指针的初级讲解的时候说过,数组的名字代表了数组的首元素地址,而这里的两个数组中放入的内容都是hello bit 那么结果是相同吗?不,并不是,请同学们仔细看,我们将hello bit 放入了两个数组中,在这里我们是开辟了两个空间,也就是这两个数组的空间,那么,两个不同的空间的地址会相同吗?所以这里的答案是不同。                                                                                                                                                                                  第二个所需判断的条件是str3和str4是否相等,在这里str3与str4所代表的是什么?你是否明白,这里我们是将hello bit 放入字符指针str3和str4中,str3和str4代表的是其首元素的地址,那么可能有人要说了,这里的结果肯定是不一样,这不跟上一个条件是一样的嘛。那么我告诉你,错了,我们来看看,这里我们到底是将什么放入了str3和str4,看好了,这里的str3和str4都代表指针,所以放入的内容肯定是指针,这里我们放入的是常量字符串,而常量字符串是在静态区是不能改变的,所以,电脑也就没有再拷贝一个字符串,就只留一个,所以str3和str4所指向的是同一个地址,所以str3==str4

2.指针数组

指针数组是什么?

指针数组就是一个存放指针的数组。

我们来类比一下,我们知道有整形数组,字符数组,其对应的就是存放整形的数组,存放字符的数组,那么指针数组就是存放指针的数组,

int main()
{
    int* p[10];//整形指针数组
    char*p[10];//一级字符指针数组
    char**p[10];//二级字符指针数组
    return 0;
}

这里我们来使用指针数组来模拟实现二维数组

 

 

这里的指针数组下标就代表了一维数组arr1 ,arr2,arr3,而一维数组中还有各自的元素 ,这样就模拟了二维数组,但是这并不是真正的二维数组,请大家记住,我们这是模拟实现二维数组。

3.数组指针

        数组指针是数组还是指针?

        答案是:指针

        我们已经了解了

                整形指针:也就是指向整形 变量的指针,存放整形变量地址的指针

                字符指针:指向字符变量的指针,存放字符变量地址的指针

        那么数组指针不就是指向了数组的指针,存放的是数组的地址

        我们来简单的分析一下:

int *p1[10];
int (*p2)[10];
//哪一个是数组指针

        我们首先分析第一行,int *p1[10],方括号[]的优先级高于*,所以p1先和方括号结合,而p1与方括号结合之后,p1就变成了数组,*就和int结合,变成了数组的类型,也就是指针,所以第一行是指针数组,第二行,*和p2被括号包围,所以p2与*结合,p2变成指针,这时int与[10]结合变成整形数组 ,所以第二行是数组指针。

        讲到这里了,大家可能会有点晕,最为方便的辨识方法呢,就是看p1,p2,你只需要观察它们到底是与谁结合,变成了什么,而余下的就是它们的类别。

        那么,我们如何使用数组指针呢?

        以前,我们在使用二维数组时,所传的形参,写的是数组,但是实际却是指针,那么,当我们学习了数组指针后,我们就能更为深入的理解二维数组传参。

        比如说我们想要实现打印二维数组的函数: 

void Printf(int(*arr)[4], int r, int c)
{
	for (int j = 0; j < 2; j++)
	{
		for (int i = 0; i < 4; i++)
			{
			printf("%d", (*(arr + j))[i]);
			}
		printf("\n");
	}
	
	
}
int main()
{
	int arr[2][4] = { 1,2,3,4,5,6,7,8 };
	Printf(arr, 2, 4);
	return 0;
}

3.函数指针

 我们在经过上面的学习后知道了数组指针是代表了指向数组的指针,那么函数指针就是指向函数的指针。

我们来看下面的代码:

从这段代码中我们可以看出Add函数的函数名和&Add的效果是一样的,所得到的结果都是相同。

所以我们可以得出结论,函数的函数名具有和数组名一样的效果,都代表了自己的地址。

 那么函数指针的基本格式是什么呢?

这里的pf就是函数指针,我们通过将Add的函数地址交给pf,然后将Add函数运算的结果给m,然后打印出m的值。

当然有了解的同学可能知道,m中,(*pf)(4,5)可以写成pf(4,5),这是为什么呢?

来看看,当我们将Add的地址放入了pf之后,此时的pf是不是就相当于Add,我们可以通过地址来直接调用函数,那么我们是不是可以直接通过pf来实现函数的使用,所以这就是原因。

接下来 我们来看一段代码:

(*(void(*)())0)();

 这里看着是不是很复杂,这里我们需要从0开始入手,void(*)()是函数指针类型,而在0前面加上类型,就是强制转换,这里将0强制转换成函数指针类型,然后在进行解引用。


 总结

        到这里,我们总共讲了不少的内容了,本篇讲解了一下指针的理解,但大家还是要多上手练习一下,听和写是两件事情。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值