数组指针、 指针数组、函数指针、函数指针数组和指向函数指针数组的指针

本篇主要介绍一下数组指针、指针数组、函数指针数组和指向函数指针数组的指针。希望能和大家一起学习,互相交流。(所讲内容的操作均在32位系统下进行)

指针数组:形如:int *p1[5];(p1为数组名)

首先我们要知道“[ ]”的优先级比“ * ”高,现在,我们不难理解,p1先与“[ ]”结合构成一个数组,然后在与“ * ”结合,说明数组的元素是指针类型,最后与“ int ”结合,说明指针指向的内容是int型的;因此,p1是一个由返回int型数据的指针所构成的数组


数组指针:形如:int(*p2)[5];


p2先与“ * ”结合,说明p2是一个指针,再与“[]”结合,说明该指针指向一个数组,最后与“int”结合,说明,该数组的元素为整型;因此,p2是一个指向由5个int类型数据组成的数组的指针


举个例子:

int main()
{
	int arr[5] = {1,2,3,4,5};
	int(*p1)[5] = &arr;
	int(*p2)[5] = arr;

	printf("%p\n",p1);
	printf("%p\n", p2);
	printf("%d\n",**p1);//使用指针

	system("pause");
	return 0;
}

输出结果:

我们可以看到p1和p2的值是一样的,但是要注意的是,虽然两个结果相同,但是它们的意义是不同的,p1是指向整个数组的地址,而p2是指向数组的首元素地址;

我们再看看编译的结果:



可以发现,对于int(*p2)[5] = arr;“=”左边的类型是指向整个数组的指针,“=”右边的类型是指向一个元素的指针。所以我们在使用的时候需要注意。(一会儿在文章最后,我会为大家总结一下怎样辨别指针的类型和指针所指向的类型

函数指针:形如:char* (*fun)(char* str1);(这是返回值类型为char*类型)

“*fun”表示这是一个指针,再与“ ()”结合表示该指针指向一个函数,这个函数参数为str1,且返回值类型为char*。

举个简单的例子:

#include<stdio.h>
#include<stdlib.h>

char* test1(char* str1)
{
	return str1;
}

char* test2(char* str2)
{
	return str2;
}


int main()
{
	char* (*fun)(char *str);
	char *str1 = "hello girl!";
	char *str2 = "hello boy!";

	//fun = test1;
	fun = &test1;//函数名可以做地址或者也可以 &+函数名,这两种写法一样
	printf("%s\n",(*fun)(str1));
	fun = test2;
	printf("%s\n", (*fun)(str2));

	system("pause");
	return 0;
}

测试结果:


接下来再看几个例子

A) char* (*fun1)(char* p1,char* p2);
B) char* *fun2(char* p1,char* p2);
C) char* fun3(char* p1,char* p2);

大家可以尝试着分析。
对于C,首先这是一个函数,该函数有两个char*类型的参数p1,p2,函数返回值类型为char*;
对于B,fun2也是一个函数,相较于C而言,唯一不同的是fun2的返回值类型为char**;
对于A,要注意的是fun1它不是函数名,它是一个指针变量,该指针指向一个函数,该函数有两个char* 类型的参数
该函数的返回值类型也是一个char* 。

还有这样一段代码:

#include<stdio.h>
#include<stdlib.h>

void Function()
{
	printf("hello girls!\n");
}
int main()
{
	void (*p)();
	*(int*)&p = (int)Function;
	(*p)();

	system("pause");
	return 0;
}
运行结果:



解析一下这段代码:

首先定义一个函数指针p,p指向一个函数,该函数无参且返回值类型为void;
(int)Function是将这个函数的入口地址强制转化为一个int类型的数据;
&p是获取指针p本身的地址,然后(int *),将其强制转化为一个指向整型数据类型的指针;
再将这个整型数据赋值给这个指针;
那么(*p)(),就是表示对函数的调用;

最后再看一个例子:(*(void(*) ())0)()

分析一下:①void(*)(),首先这是一个函数指针类型,该函数无参且无返回值;
                  ②void(*)()0,这是将0强制转化为函数指针类型,0成为了一个地址,换句话说有一个函数存在了首地址为0的一段内存区域中;
                  ③(*(void(*) ())0)表示取得这段内存区域的内容,也就是获得保存在该地址中的函数;
                  ④ (*(void(*) ())0)(),表示函数调用。

函数指针数组:形如:char* (*pf[3])(char* p);

首先明白这是一个数组,pf是数组名;数组里存储了三个元素,每个元素是一个函数指针,指针指向了一个函数,该函数的参数为char* 类型,返回值也为char*。
我们可以用它和函数指针做个比较:
函数指针 :char* (*pf)(char* p);现在我们要把它存储在数组里,这样就变成了char* (*pf[3])(char* p);

举个例子:

#include<stdio.h>
#include<stdlib.h>

char *fun1(char* p1)
{
	printf("%s\n",p1);
	return p1;
}
char *fun2(char* p2)
{
	printf("%s\n", p2);
	return p2;
}
char *fun3(char* p3)
{
	printf("%s\n", p3);
	return p3;
}

int main()
{
	char* (*pf[3])(char* p);//定义一个函数指针数组

	pf[0] = fun1;//将函数地址存入数组中
	pf[1] = fun2;
	pf[2] = fun3;

	pf[0]("hello girl!");//函数调用
	pf[1]("hello boy!");
	pf[2]("hello bit!");

	system("pause");
	return 0;
}

运行结果:



函数指针数组的指针:形如char* (*(*pf)[3])(char* p);

这里的 pf是一个指针, 指针指向了一个包含了三个元素的数组,元素是一个函数指针,指针指向了一个函数参数类型为char* ,返回值为char* 的函数。

再把它和函数指针数组做比较:

函数指针数组:char* (*pf[3])(char* p);那么函数指针的数组的指针,就要加一个“ * ”,即char* (*(*pf)[3])(char* p);

举个例子:

#include<stdio.h>
#include<stdlib.h>

char *fun1(char* p1)
{
	printf("%s\n", p1);
	return p1;
}
char *fun2(char* p2)
{
	printf("%s\n", p2);
	return p2;
}
char *fun3(char* p3)
{
	printf("%s\n", p3);
	return p3;
}

int main()
{
	char* (*pf[3])(char* p);//定义一个函数指针数组
	char* (*(*ptr)[3])(char* p);//定义一个函数指针数组的指针

	//将函数地址存放于数组中
	pf[0] = fun1;
	pf[1] = fun2;
	pf[2] = fun3;

	ptr = &pf;//将函数指针数组的地址存放于指针中

	//使用函数指针数组指针进行函数访问,接着进行函数调用
        //第一种使用数组下标访问
	ptr[0][0]("hello girl!");
	ptr[0][1]("hello boy!");
	ptr[0][2]("hello bit!");
        //第二种指针访问
	(*(*ptr + 0))("hello girl!");
	(*(*ptr + 1))("hello boy!");
	(*(*ptr + 2))("hello bit!");

	system("pause");
	return 0;
}

测试结果:



接下来为大家分享一下我自己辨别指针类型和指向指针类型的方法,希望能为大家带来帮助:

指针类型:

①int*  ptr;指针的类型是int*;
②char* ptr;指针的类型是char*;
③int** ptr;指针的类型是int**;
④int (*ptr)[3];指针的类型是int (*)[3];


指针所指向的类型:

①int*  ptr;指针所指向的类型是int;
②char* ptr;指针所指向的类型是char;
③int** ptr;指针所指向的类型是int*;
④int (*ptr)[3];指针所指向的类型是int ()[3];


希望这篇文章能为大家带来帮助,如果有错误的地方欢迎指正,大家一起交流学习!




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值