指针函数和函数指针的区别,用法,程序例子,C语言,Linux

一、指针函数

1、指针函数:首先它实质是一个函数;只是函数的返回值是一个地址量

2、通常一个函数都有返回值,如果一个函数没有返回值,则该函数是一个无值函数。

3、指针函数一般形式:

                <数据类型>    *<函数名称>(<形参说明>)

                                {

                                                语句序列;

                                                return [(表达式)];

                                }

其中:   

   <数据类型> :例如 int(整型)char(字符型) ,float(浮点型)double(双精度)等等;

与返回值的数据类型保持一致。

   <函数名称>: 符合标识符命名规则。(由字符,下划线,数字组成,且不能以数字开头)。

   <形参说明> :是“  , ”分隔的多个变量的说明形式,通常简称为形参。

   在<函数名称>之前的 * 符号,说明该函数返回一个地址常量。

   return [(表达式)]:语句中表达式的值要和函数的<数据类型>保持一致,如果函数数据类型为void则可以省略或则无表达式结果返回(即写为:return  ;

4、举例:

        注意:由于函数返回值是地址,故传递方式为地址传递,地址传递需要保证地址是有效的,需要没有被回收或释放掉的地址,否则会段错误,非法访问内存。

#include <stdio.h>
char *string()    //定义的一个char字符型的指针函数
{
	static char ch[32] = {0};
	return ch;
}

int main(int argc, char *argv[])
{ 	
	printf("%p\n",string());//打印函数返回的地址
    return 0;
} 

A、上图打印结果可以看出返回值是一个16进制的地址,并且该地址为字符数组ch的首地址。注:该地址被主函数调用并成功打印:表示该地址有效,可以正常访问。

B、如果去掉代码中的 static ,如下:

#include <stdio.h>

char *string()
{
	char ch[32] = {0};
	return ch;
}

int main(int argc, char *argv[])
{ 	
	printf("%p\n",string());
    return 0;
} 

 运行结果:这个时候不仅编译时系统会报警告:返回的地址无效,并且打印结果是空 ,这个时候主函数调用时就会非法访问内存了。

5、因此有以下几种方式在指针函数里面地址传递为有效的情况:

A、static :静态存储类型,可延长变量使用周期,但仅限于本文件内,不可跨文件使用;

#include <stdio.h>

char *string()
{
	static char ch[32] = {"hello world"};//初始化数组
	return ch;//返回字符数组ch的首地址
}

int main(int argc, char *argv[])
{ 	
	printf("%s\n",string());//%s打印字符串
    return 0;
} 

打印结果:成功打印hello world 字符串。

B、定义全局变量:

#include <stdio.h>
#include <string.h>//strcpy 函数头文件
char ch[32] = {0};//全局变量
char *string()
{
	strcpy(ch,"hello world");/向ch中写入字符串
	return ch;//返回地址
}

int main(int argc, char *argv[])
{ 	
	printf("%s\n",string());
    return 0;
} 

C、定义内部指针接收: 

#include <stdio.h>

int *sum(int a,int b)//求和函数
{	
	int m =0;
	int *p = &m;//定义一个指针保存地址
	m = a+b;
	return p;
}

char *string()
{
	char *ch = "ni hao";//字符串常量不会被立即回收
	return ch;
}

int main(int argc, char *argv[])
{ 	
	printf("%d\n",*sum(2,6));//sum返回的是p为地址;所以相当于*p
	printf("%s\n",string());
    return 0;
} 

 D、malloc开辟的地址空间:需要用户自己释放或者所以程序运行完后系统才释放;(堆区地址)

#include <stdio.h>
#include <stdlib.h>//malloc头文件
#include <string.h>//strcpy头文件
char *string()
{
	char ch[64];
	char *p = (char *)malloc(sizeof(ch));//为指针p开辟64个字节空间大小
	strcpy(p,"helllo world");//写入字符串
	return p;
}

int main(int argc, char *argv[])
{ 	
	char *s = string();//定义接收指针方便释放地址
	printf("%s\n",s);
	free(s);//释放地址
	s = NULL;//指向NULL,防止野指针
    return 0;
} 

二、函数指针

1、函数指针:实质上它是一个指针,只不过指针装的是一个函数的地址;函数地址是一个函数的入口地址。

2、当一个函数指针指向了另一个函数,就可以通过该指针来调用该函数,可以将函数作为参数传递给函数指针。

3、函数指针一般形式:

                               <数据类型> (<*函数指针名称>)(<参数说明列表>)

                                               {

                                                                语句序列;

                                                }

其中:

        <数据类型>:函数指针所指向的函数的返回值类型保持一致;

        <函数指针名称>:符合标识符命名规则;

        (<*函数指针名称>):* 符号说明为指针,( )不可缺少,表明为指向函数的指针;

        <参数说明列表>:应该与函数指针所指向的函数的形参说明保持一致;

4、举例:

#include <stdio.h>
//函数sum
int sum(int a,int b)
{
	return a+b;
}
//函数multiply
int multiply(int a,int b)
{
	return a*b;
}

int main(int argc, char *argv[])
{ 	
    //打印地址,其中加上取地址&和不加都行
	printf("%p\n",sum);//&sum
	printf("%p\n",multiply);//&multiply
    return 0;
} 

A、既然函数指针存放的是函数的地址,首先我们先打印看了一下这两个函数,计算机确实给函数名开辟了一个地址空间作为访问该函数的入口。

B、接下来便使用函数指针调用函数:

#include <stdio.h>
//求a与b的和函数
int sum(int a,int b)
{
	return a+b;
}
//求a与b的乘积函数
int multiply(int a,int b)
{
	return a*b;
}
//其中int (*pfun)(int ,int)为函数指针
int test(int a,int b,int (*pfun)(int ,int))
{
	return (*pfun)(a,b);//返回的是调用函数指针所指向的函数地址的函数
}

int main(int argc, char *argv[])
{ 	
    printf("a+b = %d\n",test(1,6,sum));//指针pfun放的sum函数的地址
    printf("a*b = %d\n",test(2,3,multiply));//指针pfun放的mutiply函数的地址
    return 0;
} 

三、函数指针的重命名

用上面的例子简单做简单改写,说明一下;

#include <stdio.h>

typedef int (*mfun)(int ,int);//重命名函数指针
//此时mfun pfun 等价于 int (*pfun)(int ,int);-->mfun装的为变量

int sum(int a,int b)
{
	return a+b;
}
int test(int a,int b,mfun pfun)
{
	return (*pfun)(a,b);
}

int main(int argc, char *argv[])
{ 	
    printf("a+b = %d\n",test(1,6,sum));
    return 0;
} 

四、总结

        总的来说,函数指针和指针函数关键抓住它存放的和返回的是什么;整体看来的话,函数指针要比指针函数用起来简单一点,指针函数虽然看起来简单,但是类型多,容易出错,关于地址传递是否有效建议看虚拟内存图,了解计算机存储数据的方式。作为一个Linux嵌入式初学者,有什么问题,欢迎大家一起交流。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值