百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术流 > 正文

C|函数指针和指针函数的联系与区别

citgpt 2024-07-10 14:44 10 浏览 0 评论

函数指针和指针函数是两个很容易混淆的概念,可以这样增直观理解:函数指针,是一个指针,一个指向函数基地址的指针,由此指针可以进行函数调用;指针函数是一个函数,一个返回指针值的函数。

1 指针函数

返回指针类型的函数简称指针函数。如用“TypeName"表示某一个数据类型,则“TypeName *pValue”表示定义一个返回TypeName类型的指针函数和一个指针变量pValue,而且这个指针变量必须正确初始化。假设这个指针变量不是通过参数表传递,而是在函数中产生,则可以表示为:

C|函数指针和指针函数的联系与区别

TypeName * FunName(参数表)

{

TypeName * pValue;

//函数体包括正确初始化指针变量pValue

//函数体

return pValue;

}

一个简单实例的代码:

//返回结构及结构指针的例子

#include <stdlib.h>

#include <stdio.h>

#include <stdlib.h>

//定义一个全局的结构体

struct LIST{

int a,b;

}d[3],*p;

//返回结构值

struct LIST make1(int x, int y)

{

struct LIST temp;

temp.a=x;

temp.b=y;

return temp;

}

//返回结构指针

struct LIST *make2(int x, int y)

{

struct LIST *temp;

temp=(struct LIST *)malloc(sizeof(struct LIST));

temp->a=x;

temp->b=y;

return temp;

}

int main()

{

int i;

d[0]=make1(215, 512);

p=make2(815,518);

d[1]=*p;

d[2]=d[0]; //结构可以整体赋值

for(i=0;i<3;i++)

printf("d[%d].a=%d,d[%d].b=%d\n", i,d[i].a,i,d[i].b);

system("pause");

return 0;

}

运行结果:

d[0].a=215,d[0].b=512

d[1].a=815,d[1].b=518

d[2].a=215,d[2].b=512

假设函数的参数表中有“TypeN *”类型的参数value,则可以表示为如下形式:

TypeName FunName(TypeName *value, 其他参数表)

{

//函数体

return value;

}

一个简单实例:

#include <stdlib.h>

//将结构指针作为返回值的例子。

#include <stdio.h>

struct LIST{

int a,b;

}d[3], b, *p;

struct LIST make(int , int); //返回结构的函数

struct LIST *change (struct LIST*, struct LIST [ ]); //返回结构的指针

void disp(struct LIST [ ]); //使用结构参数

int main()

{

d[0]=make(215,512);

d[1]=make(815,518);

d[2]=make(618,816);

p=&b; //初始化指针p

p=change(p,d); //表达式调用

disp(d);

printf("b.a=%d\t\tb.b=%d\n", b.a, b.b);

printf("p->a=%d\t\tp->b=%d\n", p->a, p->b);

system("pause");

return 0;

}

struct LIST make(int x, int y)

{

struct LIST temp;

temp.a=x;

temp.b=y;

return temp;

}

void disp(struct LIST d[ ])

{

int i;

for(i=0;i<3;i++)

printf("d[%d].a=%d\td[%d].b=%d\n", i,d[i].a,i,d[i].b);

}

//将传递的一个结构参数作为函数的返回值

struct LIST* change(struct LIST *b,struct LIST d[ ])

{

b->a=d[0].a;

b->b=d[2].b;

return b;

}

运行结果:

d[0].a=215 d[0].b=512

d[1].a=815 d[1].b=518

d[2].a=618 d[2].b=816

b.a=215 b.b=816

p->a=215 p->b=816

2 函数指针

指针变量可以指向整型变量、字符变量及字符串、浮点变量和数组。其实,指针变量也可以指向一个函数。因为尽管函数本身不是一个变量,但它在内存中仍然有其物理地址。在编译过程中,原代码被转换成目标代码,函数的入口地址也同时确立,所以就能够将函数的入口地址赋给指针变量。程序调用函数,也就是机器语言的"CALL"指向了这个入口点。因为指向函数的指针实际上包含了函数的入口点的内存地址,所以赋给指针变量的地址就是函数的入口地址,从而该指针就可以用来代替函数名。这一特性也使得函数可以作为实参传递给其他函数。

通过函数指针变量可以完成对函数的调用。其原理是通过把一个函数(函数名)赋给一个函数指针变量,然后又通过该函数指针变量来完成对函数的引用。

一个小实例:

使用函数指针输出多项式x3-4x+6和x2-3x在区间[-1,1]增长步长为0.1时的所有结果。

#include <stdlib.h>

#include <stdio.h>

double f1(double x);

double f2(double x);

//double (*p)(double);

#define STEP 0.1

int main( )

{

int i;

double x;

double (*p)(double); //double (*p)(double)与double (*p)( )等效

for ( i=0; i<2; i++)

{

printf("第%d个方程:\n",i+1);

if ( i==0)

p = f1;

//p = f1(x);

else

p = f2;

for( x = -1; x <= 1; x += STEP)

printf("%f\t%f\n", x, (*p)(x));

}

system("pause");

return 0;

}

//函数 f1

double f1(double x)

{ return ( x*x*x - 5*x -4);}

// 函数f2

double f2(double x)

{return( x*x - 3*x +2);}

运行结果:

第1个方程:

-1.000000 0.000000

-0.900000 -0.229000

-0.800000 -0.512000

-0.700000 -0.843000

-0.600000 -1.216000

-0.500000 -1.625000

-0.400000 -2.064000

-0.300000 -2.527000

-0.200000 -3.008000

-0.100000 -3.501000

-0.000000 -4.000000

0.100000 -4.499000

0.200000 -4.992000

0.300000 -5.473000

0.400000 -5.936000

0.500000 -6.375000

0.600000 -6.784000

0.700000 -7.157000

0.800000 -7.488000

0.900000 -7.771000

1.000000 -8.000000

第2个方程:

-1.000000 6.000000

-0.900000 5.510000

-0.800000 5.040000

-0.700000 4.590000

-0.600000 4.160000

-0.500000 3.750000

-0.400000 3.360000

-0.300000 2.990000

-0.200000 2.640000

-0.100000 2.310000

-0.000000 2.000000

0.100000 1.710000

0.200000 1.440000

0.300000 1.190000

0.400000 0.960000

0.500000 0.750000

0.600000 0.560000

0.700000 0.390000

0.800000 0.240000

0.900000 0.110000

1.000000 0.000000

语句double (*p)( );仅仅说明p是一个指向函数的指针变量,此函数带回实型的返回值。但这并不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,专门用来存储函数的入口地址。在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。

函数指针声明相对于函数声明,多了“(*)”符号,即多了一对圆括号和一个星号。

如果再增加一对中括号和一个数字,如double (*p[3])( );则成了一个函数指针数组变量,也就是拥有了三个函数指针,分别是p[0]、p[1]、p[2]。

函数指针还可以用作函数参数或函数返回值,具体内容请见:C|函数指针做为函数参数或函数返回值

-End-

相关推荐

js中arguments详解

一、简介了解arguments这个对象之前先来认识一下javascript的一些功能:其实Javascript并没有重载函数的功能,但是Arguments对象能够模拟重载。Javascrip中每个函数...

firewall-cmd 常用命令

目录firewalldzone说明firewallzone内容说明firewall-cmd常用参数firewall-cmd常用命令常用命令 回到顶部firewalldzone...

epel-release 是什么

EPEL-release(ExtraPackagesforEnterpriseLinux)是一个软件仓库,它为企业级Linux发行版(如CentOS、RHEL等)提供额外的软件包。以下是关于E...

FullGC详解  什么是 JVM 的 GC
FullGC详解 什么是 JVM 的 GC

前言:背景:一、什么是JVM的GC?JVM(JavaVirtualMachine)。JVM是Java程序的虚拟机,是一种实现Java语言的解...

2024-10-26 08:50 citgpt

使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
  • 使用Spire.Doc组件利用模板导出Word文档
跨域(CrossOrigin)

1.介绍  1)跨域问题:跨域问题是在网络中,当一个网络的运行脚本(通常时JavaScript)试图访问另一个网络的资源时,如果这两个网络的端口、协议和域名不一致时就会出现跨域问题。    通俗讲...

微服务架构和分布式架构的区别

1、含义不同微服务架构:微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信采用轻量级通信机制(通常用HTTP资源API)。这些服务围绕业务能力构建并...

深入理解与应用CSS clip-path 属性
深入理解与应用CSS clip-path 属性

clip-pathclip-path是什么clip-path 是一个CSS属性,允许开发者创建一个剪切区域,从而决定元素的哪些部分可见,哪些部分会被隐...

2024-10-25 11:51 citgpt

HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
  • HCNP Routing&Switching之OSPF LSA类型(二)
Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
  • Redis和Memcached的区别详解
Request.ServerVariables 大全

Request.ServerVariables("Url")返回服务器地址Request.ServerVariables("Path_Info")客户端提供的路...

python操作Kafka

目录一、python操作kafka1.python使用kafka生产者2.python使用kafka消费者3.使用docker中的kafka二、python操作kafka细...

Runtime.getRuntime().exec详解

Runtime.getRuntime().exec详解概述Runtime.getRuntime().exec用于调用外部可执行程序或系统命令,并重定向外部程序的标准输入、标准输出和标准错误到缓冲池。...

promise.all详解 promise.all是干什么的
promise.all详解 promise.all是干什么的

promise.all详解promise.all中所有的请求成功了,走.then(),在.then()中能得到一个数组,数组中是每个请求resolve抛出的结果...

2024-10-24 16:21 citgpt

Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解
  • Content-Length和Transfer-Encoding详解

取消回复欢迎 发表评论: