初始指针3

1.二级指针

我们已经知道了什么是一级指针了,一级指针就是存放变量地址的指针变量,那么同样是变量,指针变量也是有自己的地址,只不过一级指针接收的是变量的地址,那么按照一级指针的理解,二级指针就是用来接收一级指针变量的地址,下面就是二级指针。

当然我们也是可以通过二级指针解引用来获得变量a的值,相互转换就如以下可以知道。

*ppa=pa

*ppa==&a

* *ppa==*&a

*&a==a

2.指针数组

什么是指针数组呢?我们可以通过类比法可以知道,我们知道有整型数组(存放整型的数组)、字符数组(存放字符的数组)、浮点型数组(存放浮点型的数组),那么我们通过类比就可以得知:指针数组就是用于存放指针/地址的数组。

指针数组的每个元素都是用来存放地址(指针)的。例如下图,指针数组的每个元素都是地址,又可以指向一块区域。

3.指针数组模拟二维数组

#include <stdio.h>
int main()
{
 int arr1[] = {1,2,3,4,5};
 int arr2[] = {2,3,4,5,6};
 int arr3[] = {3,4,5,6,7};
 //数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
 int* parr[3] = {arr1, arr2, arr3};
 int i = 0;
 int j = 0;
 for(i=0; i<3; i++)
 {
     for(j=0; j<5; j++)
     {
         printf("%d ", parr[i][j]);//parr[i][j]可以写成*(*(parr+i)+j),两者都是一样的
     }
     printf("\n");
 }
 return 0;
}

从运行结果可以看出输出的结果是一个二维数组。

4.字符指针变量

我们已经知道了整型指针变量了,是存放整形变量的地址。那自然而然的,字符指针变量就是存放字符变量的地址

上图是我们常用的表示方法,但是还有一种使用方式如下:

其实并不是,这里的意思是把hello world这个字符串的首字符的地址放到了pstr中,也就是把h的地址放到了pstr中。

5.数组指针变量

我们在上面知道了指针数组是一个用于存放指针的数组,那么现在碰到的数组指针是什么呢?

我们刚刚知道了字符指针变量是用于存放字符变量的地址,那么通过类比可知,数组指针变量是用于存放数组的地址的指针变量。下面给大家看一下数组指针的形式

这里的p先与*结合,说明p是数组指针变量,然后指向的是一个大小为10的整形数组,所以p是一个指针,指向一个数组,叫数组指针。

这⾥要注意:[]的优先级要⾼于*号的,所以必须加上()来保证p先和*结合。

6.二维数组传参的本质

在前面我们已经知道了一维数组传参的本质,形式有两种,那么二维数组传参的本质也同样是有两种,跟一维数组传参是大同小异,话不多说,我们来通过代码的形式理解        

#include<stdio.h>
void test(int a[][5], int x, int y)
{
	for (int i = 0; i < x; i++)//控制行
	{
		for (int j = 0; j < y; j++)//控制列
		{
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int a[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	test(a, 3, 5);
	return 0;
}

运行结果如下:

上面是一种二维数组传参形式,还有一种那就是通过指针来接收,在前面我们已经知道,数组名是数组首元素的地址,那么我们传参过去的时候传的就是数组首元素的地址,我们知道二维数组其实就是一维数组的数组,那我们传过去的就是即就是第一行的地址,也就是一维数组的地址,但是每一行里边还有五个元素,那么我们就通过传过去的指针再指向这五个元素就可以了,如下图

#include<stdio.h>
void test(int (*p)[5], int x, int y)
{
	for (int i = 0; i < x; i++)
	{
		for (int j = 0; j < y; j++)
		{
			printf("%d ", *(*(p+i)+j));
		}
		printf("\n");
	}
}
int main()
{
	int a[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	test(a, 3, 5);
	return 0;
}

从中看出,p接收了二维数组中行的地址,然后p再指向每一行中的五个元素,这样就可以得到每一个元素

7.函数指针变量

根据数组指针以及字符指针类比,可以知道,函数指针变量就是用于存放函数地址的指针变量

但是&函数名与函数名的地址有什么区别吗?下面这段代码可以给我们解答。

从中可以看出,无论是&函数名还是函数名的地址都是一样的,这就跟数组有点类似,但还是有所差别。下面我来总结一下这两种区别:

&数组名:取出的是整个数组的地址。

数组名:数组名是数组首元素的地址。

&函数名:得到的是函数的地址。

函数名:得到的也是函数的地址。

以下是函数指针变量的形式:

那么函数指针应该怎么使用呢?

上面的代码,我们可以看到在输出的时候不论pf是否解引用,输出的结果都是正确的。

8.typedef关键字

typedef是用来重命名的,可以将复杂的类型简单化

例如,unsigned int写起来不方便,我想用uint来代替它,那么我们可以这么写:

typedef unsigned int uint;

这么写之后,后面的代码如果要用到unsigned int 的话都可以用uint来代替它。

但是如果是指针类型我们应该这么重新命名呢?其实跟上面差不多。

typedef int* ptr_t;

这个就可以同ptr_t来代替整型指针int*了。

但是在重新命名函数指针和数组指针的时候就会有点差别。

typedef int (*parr_t)[5];//这里把int (*)[5]重命名为parr_t;需要注意的是命名的名字要放在*的右边

 9.总结

通过这篇博客学习知道了,1.二级指针就是用来存放一级指针变量自身的地址的,通过双重解引用就可以得到变量的值;2.指针数组是存放指针的数组,数组中的每一个元素都是地址;3.字符指针是用来存放字符变量的地址的变量,字符指针有两种使用方式;4.数组指针是存放数组的地址的变量;5.二维数组传参与一维数组传参是差不多的,二维数组其实就是一维数组里还有个数组,用指针接收时,接收的是二维数组中第一个元素的地址,也就是第一行的地址;6.函数指针变量中的函数名与&函数名都是代表的是函数的地址;7.typedef可以对复杂的名字进行重命名使得简单化。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值